Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[sfrench/cifs-2.6.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3   Copyright (c) Eicon Networks, 2002.
4  *
5   This source file is supplied for the use with
6   Eicon Networks range of DIVA Server Adapters.
7  *
8   Eicon File Revision :    2.1
9  *
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2, or (at your option)
13   any later version.
14  *
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18   See the GNU General Public License for more details.
19  *
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67  */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
75 static void set_group_ind_mask (PLCI   *plci);
76 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
77 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL   *, CAPI_MSG   *);
82 static word api_parse(byte   *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
84 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI   *);
90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
92
93 void   callback(ENTITY   *);
94
95 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI   *, byte);
97 static void data_ack(PLCI   *, byte);
98 static void sig_ind(PLCI   *);
99 static void SendInfo(PLCI   *, dword, byte   * *, byte);
100 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
101 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
102
103 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
104
105 static void nl_ind(PLCI   *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER   *);
133 static void add_p(PLCI   *, byte, byte   *);
134 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
137 static void add_d(PLCI   *, word, byte   *);
138 static void add_ai(PLCI   *, API_PARSE *);
139 static word add_b1(PLCI   *, API_PARSE *, word, word);
140 static word add_b23(PLCI   *, API_PARSE *);
141 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI   *, byte, byte);
143 static void nl_req_ncci(PLCI   *, byte, byte);
144 static void send_req(PLCI   *);
145 static void send_data(PLCI   *);
146 static word plci_remove_check(PLCI   *);
147 static void listen_check(DIVA_CAPI_ADAPTER   *);
148 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI   *, word *, byte   **, byte);
151 static byte ie_compare(byte   *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
153 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
154
155 /*
156   XON protocol helpers
157   */
158 static void channel_flow_control_remove (PLCI   * plci);
159 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI   * plci, byte ch);
161 static void channel_request_xon (PLCI   * plci, byte ch);
162 static void channel_xmit_xon (PLCI   * plci);
163 static int channel_can_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI   * plci);
165
166 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
169 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
170 static void VoiceChannelOff(PLCI   *plci);
171 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
172 static void adv_voice_clear_config (PLCI   *plci);
173
174 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
189 static void init_b1_config (PLCI   *plci);
190 static void clear_b1_config (PLCI   *plci);
191
192 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI   *plci);
195 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
196 static void dtmf_parameter_write (PLCI   *plci);
197
198
199 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
201 static void mixer_clear_config (PLCI   *plci);
202 static void mixer_notify_update (PLCI   *plci, byte others);
203 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_remove (PLCI   *plci);
209
210
211 static void ec_command (dword Id, PLCI   *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
214
215
216 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
218
219
220 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
221 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231
232 void   sendf(APPL   *, word, dword, word, byte *, ...);
233 void   * TransmitBufferSet(APPL   * appl, dword ref);
234 void   * TransmitBufferGet(APPL   * appl, void   * p);
235 void TransmitBufferFree(APPL   * appl, void   * p);
236 void   * ReceiveBufferGet(APPL   * appl, int Num);
237
238 int fax_head_line_time (char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER   * adapter;
247 extern APPL   * application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260   word command;
261   byte * format;
262   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
263 } ftable[] = {
264   {_DATA_B3_R,                          "dwww",         data_b3_req},
265   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
266   {_INFO_R,                             "ss",           info_req},
267   {_INFO_I|RESPONSE,                    "",             info_res},
268   {_CONNECT_R,                          "wsssssssss",   connect_req},
269   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
270   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
271   {_DISCONNECT_R,                       "s",            disconnect_req},
272   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
273   {_LISTEN_R,                           "dddss",        listen_req},
274   {_ALERT_R,                            "s",            alert_req},
275   {_FACILITY_R,                         "ws",           facility_req},
276   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
277   {_CONNECT_B3_R,                       "s",            connect_b3_req},
278   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
279   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
280   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
282   {_RESET_B3_R,                         "s",            reset_b3_req},
283   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
284   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
286   {_SELECT_B_REQ,                       "s",            select_b_req},
287   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
289   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
290 };
291
292 static byte * cip_bc[29][2] = {
293   { "",                     ""                     }, /* 0 */
294   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303   { "",                     ""                     }, /* 10 */
304   { "",                     ""                     }, /* 11 */
305   { "",                     ""                     }, /* 12 */
306   { "",                     ""                     }, /* 13 */
307   { "",                     ""                     }, /* 14 */
308   { "",                     ""                     }, /* 15 */
309
310   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte * cip_hlc[29] = {
326   "",                           /* 0 */
327   "",                           /* 1 */
328   "",                           /* 2 */
329   "",                           /* 3 */
330   "",                           /* 4 */
331   "",                           /* 5 */
332   "",                           /* 6 */
333   "",                           /* 7 */
334   "",                           /* 8 */
335   "",                           /* 9 */
336   "",                           /* 10 */
337   "",                           /* 11 */
338   "",                           /* 12 */
339   "",                           /* 13 */
340   "",                           /* 14 */
341   "",                           /* 15 */
342
343   "\x02\x91\x81",               /* 16 */
344   "\x02\x91\x84",               /* 17 */
345   "\x02\x91\xa1",               /* 18 */
346   "\x02\x91\xa4",               /* 19 */
347   "\x02\x91\xa8",               /* 20 */
348   "\x02\x91\xb1",               /* 21 */
349   "\x02\x91\xb2",               /* 22 */
350   "\x02\x91\xb5",               /* 23 */
351   "\x02\x91\xb8",               /* 24 */
352   "\x02\x91\xc1",               /* 25 */
353   "\x02\x91\x81",               /* 26 */
354   "\x03\x91\xe0\x01",           /* 27 */
355   "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL   * appl, CAPI_MSG   * msg)
387 {
388   word i, j, k, l, n;
389   word ret;
390   byte c;
391   byte controller;
392   DIVA_CAPI_ADAPTER   * a;
393   PLCI   * plci;
394   NCCI   * ncci_ptr;
395   word ncci;
396   CAPI_MSG   *m;
397     API_PARSE msg_parms[MAX_MSG_PARMS+1];
398
399   if (msg->header.length < sizeof (msg->header) ||
400       msg->header.length > MAX_MSG_SIZE) {
401     dbug(1,dprintf("bad len"));
402     return _BAD_MSG;
403   }
404
405   controller = (byte)((msg->header.controller &0x7f)-1);
406
407   /* controller starts with 0 up to (max_adapter - 1) */
408   if ( controller >= max_adapter )
409   {
410     dbug(1,dprintf("invalid ctrl"));
411     return _BAD_MSG;
412   }
413   
414   a = &adapter[controller];
415   plci = NULL;
416   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417   {
418     dbug(1,dprintf("plci=%x",msg->header.plci));
419     plci = &a->plci[msg->header.plci-1];
420     ncci = GET_WORD(&msg->header.ncci);
421     if (plci->Id
422      && (plci->appl
423       || (plci->State == INC_CON_PENDING)
424       || (plci->State == INC_CON_ALERT)
425       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426      && ((ncci == 0)
427       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429     {
430       i = plci->msg_in_read_pos;
431       j = plci->msg_in_write_pos;
432       if (j >= i)
433       {
434         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435           i += MSG_IN_QUEUE_SIZE - j;
436         else
437           j = 0;
438       }
439       else
440       {
441
442         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444         if (i > MSG_IN_QUEUE_SIZE - n)
445           i = MSG_IN_QUEUE_SIZE - n + 1;
446         i -= j;
447       }
448
449       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451       {
452         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453           msg->header.length, plci->msg_in_write_pos,
454           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456         return _QUEUE_FULL;
457       }
458       c = false;
459       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
460        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461       {
462         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463           c = true;
464       }
465       if (msg->header.command == _DATA_B3_R)
466       {
467         if (msg->header.length < 20)
468         {
469           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470           return _BAD_MSG;
471         }
472         ncci_ptr = &(a->ncci[ncci]);
473         n = ncci_ptr->data_pending;
474         l = ncci_ptr->data_ack_pending;
475         k = plci->msg_in_read_pos;
476         while (k != plci->msg_in_write_pos)
477         {
478           if (k == plci->msg_in_wrap_pos)
479             k = 0;
480           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482           {
483             n++;
484             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485               l++;
486           }
487
488           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
489             MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491         }
492         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493         {
494           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497           return _QUEUE_FULL;
498         }
499         if (plci->req_in || plci->internal_command)
500         {
501           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
502            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503           {
504             dbug(0,dprintf("Q-FULL3(requeue)"));
505
506             return _QUEUE_FULL;
507           }
508           c = true;
509         }
510       }
511       else
512       {
513         if (plci->req_in || plci->internal_command)
514           c = true;
515         else
516         {
517           plci->command = msg->header.command;
518           plci->number = msg->header.number;
519         }
520       }
521       if (c)
522       {
523         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524           msg->header.command, plci->req_in, plci->internal_command,
525           msg->header.length, plci->msg_in_write_pos,
526           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527         if (j == 0)
528           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
530         for (i = 0; i < msg->header.length; i++)
531           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
532         if (m->header.command == _DATA_B3_R)
533         {
534
535           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
536
537         }
538
539         j = (j + 3) & 0xfffc;
540
541         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
542         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543         return 0;
544       }
545     }
546     else
547     {
548       plci = NULL;
549     }
550   }
551   dbug(1,dprintf("com=%x",msg->header.command));
552
553   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554   for(i=0, ret = _BAD_MSG;
555       i<(sizeof(ftable)/sizeof(struct _ftable));
556       i++) {
557
558     if(ftable[i].command==msg->header.command) {
559       /* break loop if the message is correct, otherwise continue scan  */
560       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
561       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
562         ret = 0;
563         break;
564       }
565       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
566     }
567   }
568   if(ret) {
569     dbug(1,dprintf("BAD_MSG"));
570     if(plci) plci->command = 0;
571     return ret;
572   }
573
574
575   c = ftable[i].function(GET_DWORD(&msg->header.controller),
576                          msg->header.number,
577                          a,
578                          plci,
579                          appl,
580                          msg_parms);
581
582   channel_xmit_extended_xon (plci);
583
584   if(c==1) send_req(plci);
585   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
586   if(plci && !plci->req_in) plci->command = 0;
587   return 0;
588 }
589
590
591 /*------------------------------------------------------------------*/
592 /* api_parse function, check the format of api messages             */
593 /*------------------------------------------------------------------*/
594
595 word api_parse(byte   * msg, word length, byte * format, API_PARSE * parms)
596 {
597   word i;
598   word p;
599
600   for(i=0,p=0; format[i]; i++) {
601     if(parms)
602     {
603       parms[i].info = &msg[p];
604     }
605     switch(format[i]) {
606     case 'b':
607       p +=1;
608       break;
609     case 'w':
610       p +=2;
611       break;
612     case 'd':
613       p +=4;
614       break;
615     case 's':
616       if(msg[p]==0xff) {
617         parms[i].info +=2;
618         parms[i].length = msg[p+1] + (msg[p+2]<<8);
619         p +=(parms[i].length +3);
620       }
621       else {
622         parms[i].length = msg[p];
623         p +=(parms[i].length +1);
624       }
625       break;
626     }
627
628     if(p>length) return true;
629   }
630   if(parms) parms[i].info = NULL;
631   return false;
632 }
633
634 void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
635 {
636   word i, j, n = 0;
637   byte   *p;
638
639   p = out->info;
640   for (i = 0; format[i] != '\0'; i++)
641   {
642     out->parms[i].info = p;
643     out->parms[i].length = in[i].length;
644     switch (format[i])
645     {
646     case 'b':
647       n = 1;
648       break;
649     case 'w':
650       n = 2;
651       break;
652     case 'd':
653       n = 4;
654       break;
655     case 's':
656       n = in[i].length + 1;
657       break;
658     }
659     for (j = 0; j < n; j++)
660       *(p++) = in[i].info[j];
661   }
662   out->parms[i].info = NULL;
663   out->parms[i].length = 0;
664 }
665
666 void api_load_msg(API_SAVE   *in, API_PARSE   *out)
667 {
668   word i;
669
670   i = 0;
671   do
672   {
673     out[i].info = in->parms[i].info;
674     out[i].length = in->parms[i].length;
675   } while (in->parms[i++].info);
676 }
677
678
679 /*------------------------------------------------------------------*/
680 /* CAPI remove function                                             */
681 /*------------------------------------------------------------------*/
682
683 word api_remove_start(void)
684 {
685   word i;
686   word j;
687
688   if(!remove_started) {
689     remove_started = true;
690     for(i=0;i<max_adapter;i++) {
691       if(adapter[i].request) {
692         for(j=0;j<adapter[i].max_plci;j++) {
693           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
694         }
695       }
696     }
697     return 1;
698   }
699   else {
700     for(i=0;i<max_adapter;i++) {
701       if(adapter[i].request) {
702         for(j=0;j<adapter[i].max_plci;j++) {
703           if(adapter[i].plci[j].Sig.Id) return 1;
704         }
705       }
706     }
707   }
708   api_remove_complete();
709   return 0;
710 }
711
712
713 /*------------------------------------------------------------------*/
714 /* internal command queue                                           */
715 /*------------------------------------------------------------------*/
716
717 static void init_internal_command_queue (PLCI   *plci)
718 {
719   word i;
720
721   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
722     (char   *)(FILE_), __LINE__));
723
724   plci->internal_command = 0;
725   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
726     plci->internal_command_queue[i] = NULL;
727 }
728
729
730 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
731 {
732   word i;
733
734   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
735     UnMapId (Id), (char   *)(FILE_), __LINE__));
736
737   if (plci->internal_command == 0)
738   {
739     plci->internal_command_queue[0] = command_function;
740     (* command_function)(Id, plci, OK);
741   }
742   else
743   {
744     i = 1;
745     while (plci->internal_command_queue[i] != 0)
746       i++;
747     plci->internal_command_queue[i] = command_function;
748   }
749 }
750
751
752 static void next_internal_command (dword Id, PLCI   *plci)
753 {
754   word i;
755
756   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
757     UnMapId (Id), (char   *)(FILE_), __LINE__));
758
759   plci->internal_command = 0;
760   plci->internal_command_queue[0] = NULL;
761   while (plci->internal_command_queue[1] != 0)
762   {
763     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
764       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
765     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
766     (*(plci->internal_command_queue[0]))(Id, plci, OK);
767     if (plci->internal_command != 0)
768       return;
769     plci->internal_command_queue[0] = NULL;
770   }
771 }
772
773
774 /*------------------------------------------------------------------*/
775 /* NCCI allocate/remove function                                    */
776 /*------------------------------------------------------------------*/
777
778 static dword ncci_mapping_bug = 0;
779
780 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
781 {
782   DIVA_CAPI_ADAPTER   *a;
783   word ncci, i, j, k;
784
785   a = plci->adapter;
786   if (!ch || a->ch_ncci[ch])
787   {
788     ncci_mapping_bug++;
789     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
790       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
791     ncci = ch;
792   }
793   else
794   {
795     if (force_ncci)
796       ncci = force_ncci;
797     else
798     {
799       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
800         ncci = ch;
801       else
802       {
803         ncci = 1;
804         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
805           ncci++;
806         if (ncci == MAX_NCCI+1)
807         {
808           ncci_mapping_bug++;
809           i = 1;
810           do
811           {
812             j = 1;
813             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
814               j++;
815             k = j;
816             if (j < MAX_NCCI+1)
817             {
818               do
819               {
820                 j++;
821               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
822             }
823           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
824           if (i < MAX_NL_CHANNEL+1)
825           {
826             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
827               ncci_mapping_bug, ch, force_ncci, i, k, j));
828           }
829           else
830           {
831             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
832               ncci_mapping_bug, ch, force_ncci));
833           }
834           ncci = ch;
835         }
836       }
837       a->ncci_plci[ncci] = plci->Id;
838       a->ncci_state[ncci] = IDLE;
839       if (!plci->ncci_ring_list)
840         plci->ncci_ring_list = ncci;
841       else
842         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
843       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
844     }
845     a->ncci_ch[ncci] = ch;
846     a->ch_ncci[ch] = (byte) ncci;
847     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
848       ncci_mapping_bug, ch, force_ncci, ch, ncci));
849   }
850   return (ncci);
851 }
852
853
854 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
855 {
856   DIVA_CAPI_ADAPTER   *a;
857   APPL   *appl;
858   word i, ncci_code;
859   dword Id;
860
861   a = plci->adapter;
862   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
863   if (ncci)
864   {
865     if (a->ncci_plci[ncci] == plci->Id)
866     {
867       if (!plci->appl)
868       {
869         ncci_mapping_bug++;
870         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
871           ncci_mapping_bug, Id));
872       }
873       else
874       {
875         appl = plci->appl;
876         ncci_code = ncci | (((word) a->Id) << 8);
877         for (i = 0; i < appl->MaxBuffer; i++)
878         {
879           if ((appl->DataNCCI[i] == ncci_code)
880            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
881           {
882             appl->DataNCCI[i] = 0;
883           }
884         }
885       }
886     }
887   }
888   else
889   {
890     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
891     {
892       if (a->ncci_plci[ncci] == plci->Id)
893       {
894         if (!plci->appl)
895         {
896           ncci_mapping_bug++;
897           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
898             ncci_mapping_bug, Id));
899         }
900         else
901         {
902           appl = plci->appl;
903           ncci_code = ncci | (((word) a->Id) << 8);
904           for (i = 0; i < appl->MaxBuffer; i++)
905           {
906             if ((appl->DataNCCI[i] == ncci_code)
907              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
908             {
909               appl->DataNCCI[i] = 0;
910             }
911           }
912         }
913       }
914     }
915   }
916 }
917
918
919 static void cleanup_ncci_data (PLCI   *plci, word ncci)
920 {
921   NCCI   *ncci_ptr;
922
923   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
924   {
925     ncci_ptr = &(plci->adapter->ncci[ncci]);
926     if (plci->appl)
927     {
928       while (ncci_ptr->data_pending != 0)
929       {
930         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
931           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
932         (ncci_ptr->data_out)++;
933         if (ncci_ptr->data_out == MAX_DATA_B3)
934           ncci_ptr->data_out = 0;
935         (ncci_ptr->data_pending)--;
936       }
937     }
938     ncci_ptr->data_out = 0;
939     ncci_ptr->data_pending = 0;
940     ncci_ptr->data_ack_out = 0;
941     ncci_ptr->data_ack_pending = 0;
942   }
943 }
944
945
946 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
947 {
948   DIVA_CAPI_ADAPTER   *a;
949   dword Id;
950   word i;
951
952   a = plci->adapter;
953   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
954   if (!preserve_ncci)
955     ncci_free_receive_buffers (plci, ncci);
956   if (ncci)
957   {
958     if (a->ncci_plci[ncci] != plci->Id)
959     {
960       ncci_mapping_bug++;
961       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
962         ncci_mapping_bug, Id, preserve_ncci));
963     }
964     else
965     {
966       cleanup_ncci_data (plci, ncci);
967       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
968         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
969       a->ch_ncci[a->ncci_ch[ncci]] = 0;
970       if (!preserve_ncci)
971       {
972         a->ncci_ch[ncci] = 0;
973         a->ncci_plci[ncci] = 0;
974         a->ncci_state[ncci] = IDLE;
975         i = plci->ncci_ring_list;
976         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
977           i = a->ncci_next[i];
978         if ((i != 0) && (a->ncci_next[i] == ncci))
979         {
980           if (i == ncci)
981             plci->ncci_ring_list = 0;
982           else if (plci->ncci_ring_list == ncci)
983             plci->ncci_ring_list = i;
984           a->ncci_next[i] = a->ncci_next[ncci];
985         }
986         a->ncci_next[ncci] = 0;
987       }
988     }
989   }
990   else
991   {
992     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
993     {
994       if (a->ncci_plci[ncci] == plci->Id)
995       {
996         cleanup_ncci_data (plci, ncci);
997         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
998           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
999         a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000         if (!preserve_ncci)
1001         {
1002           a->ncci_ch[ncci] = 0;
1003           a->ncci_plci[ncci] = 0;
1004           a->ncci_state[ncci] = IDLE;
1005           a->ncci_next[ncci] = 0;
1006         }
1007       }
1008     }
1009     if (!preserve_ncci)
1010       plci->ncci_ring_list = 0;
1011   }
1012 }
1013
1014
1015 /*------------------------------------------------------------------*/
1016 /* PLCI remove function                                             */
1017 /*------------------------------------------------------------------*/
1018
1019 static void plci_free_msg_in_queue (PLCI   *plci)
1020 {
1021   word i;
1022
1023   if (plci->appl)
1024   {
1025     i = plci->msg_in_read_pos;
1026     while (i != plci->msg_in_write_pos)
1027     {
1028       if (i == plci->msg_in_wrap_pos)
1029         i = 0;
1030       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031       {
1032
1033         TransmitBufferFree (plci->appl,
1034           (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1035
1036       }
1037
1038       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1039         MSG_IN_OVERHEAD + 3) & 0xfffc;
1040
1041     }
1042   }
1043   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1046 }
1047
1048
1049 static void plci_remove(PLCI   * plci)
1050 {
1051
1052   if(!plci) {
1053     dbug(1,dprintf("plci_remove(no plci)"));
1054     return;
1055   }
1056   init_internal_command_queue (plci);
1057   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058   if(plci_remove_check(plci))
1059   {
1060     return;
1061   }
1062   if (plci->Sig.Id == 0xff)
1063   {
1064     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065     if (plci->NL.Id && !plci->nl_remove_id)
1066     {
1067       nl_req_ncci(plci,REMOVE,0);
1068       send_req(plci);
1069     }
1070   }
1071   else
1072   {
1073     if (!plci->sig_remove_id
1074      && (plci->Sig.Id
1075       || (plci->req_in!=plci->req_out)
1076       || (plci->nl_req || plci->sig_req)))
1077     {
1078       sig_req(plci,HANGUP,0);
1079       send_req(plci);
1080     }
1081   }
1082   ncci_remove (plci, 0, false);
1083   plci_free_msg_in_queue (plci);
1084
1085   plci->channels = 0;
1086   plci->appl = NULL;
1087   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088     plci->State = OUTG_DIS_PENDING;
1089 }
1090
1091 /*------------------------------------------------------------------*/
1092 /* Application Group function helpers                               */
1093 /*------------------------------------------------------------------*/
1094
1095 static void set_group_ind_mask (PLCI   *plci)
1096 {
1097   word i;
1098
1099   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100     plci->group_optimization_mask_table[i] = 0xffffffffL;
1101 }
1102
1103 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1104 {
1105   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106 }
1107
1108 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1109 {
1110   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111 }
1112
1113 /*------------------------------------------------------------------*/
1114 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1115 /*------------------------------------------------------------------*/
1116
1117 static void clear_c_ind_mask (PLCI   *plci)
1118 {
1119   word i;
1120
1121   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122     plci->c_ind_mask_table[i] = 0;
1123 }
1124
1125 static byte c_ind_mask_empty (PLCI   *plci)
1126 {
1127   word i;
1128
1129   i = 0;
1130   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1131     i++;
1132   return (i == C_IND_MASK_DWORDS);
1133 }
1134
1135 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1136 {
1137   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138 }
1139
1140 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1141 {
1142   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143 }
1144
1145 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1146 {
1147   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148 }
1149
1150 static void dump_c_ind_mask (PLCI   *plci)
1151 {
1152 static char hex_digit_table[0x10] =
1153   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1154   word i, j, k;
1155   dword d;
1156     char *p;
1157     char buf[40];
1158
1159   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1160   {
1161     p = buf + 36;
1162     *p = '\0';
1163     for (j = 0; j < 4; j++)
1164     {
1165       if (i+j < C_IND_MASK_DWORDS)
1166       {
1167         d = plci->c_ind_mask_table[i+j];
1168         for (k = 0; k < 8; k++)
1169         {
1170           *(--p) = hex_digit_table[d & 0xf];
1171           d >>= 4;
1172         }
1173       }
1174       else if (i != 0)
1175       {
1176         for (k = 0; k < 8; k++)
1177           *(--p) = ' ';
1178       }
1179       *(--p) = ' ';
1180     }
1181     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1182   }
1183 }
1184
1185
1186
1187
1188
1189 #define dump_plcis(a)
1190
1191
1192
1193 /*------------------------------------------------------------------*/
1194 /* translation function for each message                            */
1195 /*------------------------------------------------------------------*/
1196
1197 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1198 {
1199   word ch;
1200   word i;
1201   word Info;
1202   word CIP;
1203   byte LinkLayer;
1204   API_PARSE * ai;
1205   API_PARSE * bp;
1206     API_PARSE ai_parms[5];
1207   word channel = 0;
1208   dword ch_mask;
1209   byte m;
1210   static byte esc_chi[35] = {0x02,0x18,0x01};
1211   static byte lli[2] = {0x01,0x00};
1212   byte noCh = 0;
1213   word dir = 0;
1214   byte   *p_chi = "";
1215
1216   for(i=0;i<5;i++) ai_parms[i].length = 0;
1217
1218   dbug(1,dprintf("connect_req(%d)",parms->length));
1219   Info = _WRONG_IDENTIFIER;
1220   if(a)
1221   {
1222     if(a->adapter_disabled)
1223     {
1224       dbug(1,dprintf("adapter disabled"));
1225       Id = ((word)1<<8)|a->Id;
1226       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1227       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1228       return false;
1229     }
1230     Info = _OUT_OF_PLCI;
1231     if((i=get_plci(a)))
1232     {
1233       Info = 0;
1234       plci = &a->plci[i-1];
1235       plci->appl = appl;
1236       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1237       /* check 'external controller' bit for codec support */
1238       if(Id & EXT_CONTROLLER)
1239       {
1240         if(AdvCodecSupport(a, plci, appl, 0) )
1241         {
1242           plci->Id = 0;
1243           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1244           return 2;
1245         }
1246       }
1247       ai = &parms[9];
1248       bp = &parms[5];
1249       ch = 0;
1250       if(bp->length)LinkLayer = bp->info[3];
1251       else LinkLayer = 0;
1252       if(ai->length)
1253       {
1254         ch=0xffff;
1255         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1256         {
1257           ch = 0;
1258           if(ai_parms[0].length)
1259           {
1260             ch = GET_WORD(ai_parms[0].info+1);
1261             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1262             if(ch==4) /* explizit CHI in message */
1263             {
1264               /* check length of B-CH struct */
1265               if((ai_parms[0].info)[3]>=1)
1266               {
1267                 if((ai_parms[0].info)[4]==CHI)
1268                 {
1269                   p_chi = &((ai_parms[0].info)[5]);
1270                 }
1271                 else
1272                 {
1273                   p_chi = &((ai_parms[0].info)[3]);
1274                 }
1275                 if(p_chi[0]>35) /* check length of channel ID */
1276                 {
1277                   Info = _WRONG_MESSAGE_FORMAT;    
1278                 }
1279               }
1280               else Info = _WRONG_MESSAGE_FORMAT;    
1281             }
1282
1283             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1284             {
1285               dir = GET_WORD(ai_parms[0].info+3);
1286               ch_mask = 0;
1287               m = 0x3f;
1288               for(i=0; i+5<=ai_parms[0].length; i++)
1289               {
1290                 if(ai_parms[0].info[i+5]!=0)
1291                 {
1292                   if((ai_parms[0].info[i+5] | m) != 0xff)
1293                     Info = _WRONG_MESSAGE_FORMAT;
1294                   else
1295                   {
1296                     if (ch_mask == 0)
1297                       channel = i;
1298                     ch_mask |= 1L << i;
1299                   }
1300                 }
1301                 m = 0;
1302               }
1303               if (ch_mask == 0)
1304                 Info = _WRONG_MESSAGE_FORMAT;
1305               if (!Info)
1306               {
1307                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1308                 {
1309                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1310                   for(i=0; i+5<=ai_parms[0].length; i++)
1311                     esc_chi[i+3] = ai_parms[0].info[i+5];
1312                 }
1313                 else
1314                   esc_chi[0] = 2;
1315                 esc_chi[2] = (byte)channel;
1316                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1317                 add_p(plci,LLI,lli);
1318                 add_p(plci,ESC,esc_chi);
1319                 plci->State = LOCAL_CONNECT;
1320                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1321               }
1322             }
1323           }
1324         }
1325         else  Info = _WRONG_MESSAGE_FORMAT;
1326       }
1327
1328       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1329       plci->command = _CONNECT_R;
1330       plci->number = Number;
1331       /* x.31 or D-ch free SAPI in LinkLayer? */
1332       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1333       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1334       {
1335         /* B-channel used for B3 connections (ch==0), or no B channel    */
1336         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1337         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1338         else     Info = add_b1(plci,&parms[5],ch,0); 
1339         add_s(plci,OAD,&parms[2]);
1340         add_s(plci,OSA,&parms[4]);
1341         add_s(plci,BC,&parms[6]);
1342         add_s(plci,LLC,&parms[7]);
1343         add_s(plci,HLC,&parms[8]);
1344         CIP = GET_WORD(parms[0].info);
1345         if (a->Info_Mask[appl->Id-1] & 0x200)
1346         {
1347           /* early B3 connect (CIP mask bit 9) no release after a disc */
1348           add_p(plci,LLI,"\x01\x01");
1349         }
1350         if(GET_WORD(parms[0].info)<29) {
1351           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1352           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1353         }
1354         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1355         sig_req(plci,ASSIGN,DSIG_ID);
1356       }
1357       else if(ch==1) {
1358
1359         /* D-Channel used for B3 connections */
1360         plci->Sig.Id = 0xff;
1361         Info = 0;
1362       }
1363
1364       if(!Info && ch!=2 && !noCh ) {
1365         Info = add_b23(plci,&parms[5]);
1366         if(!Info) {
1367           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1368         }
1369       }
1370
1371       if(!Info)
1372       {
1373         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1374         {
1375           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1376           {
1377             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1378             plci->spoofed_msg = CALL_REQ;
1379             plci->internal_command = BLOCK_PLCI;
1380             plci->command = 0;
1381             dbug(1,dprintf("Spoof"));
1382             send_req(plci);
1383             return false;
1384           }
1385           if(ch==4)add_p(plci,CHI,p_chi);
1386           add_s(plci,CPN,&parms[1]);
1387           add_s(plci,DSA,&parms[3]);
1388           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1389           add_ai(plci,&parms[9]);
1390           if(!dir)sig_req(plci,CALL_REQ,0);
1391           else
1392           {
1393             plci->command = PERM_LIST_REQ;
1394             plci->appl = appl;
1395             sig_req(plci,LISTEN_REQ,0);
1396             send_req(plci);
1397             return false;
1398           }
1399         }
1400         send_req(plci);
1401         return false;
1402       }
1403       plci->Id = 0;
1404     }
1405   }
1406   sendf(appl,
1407         _CONNECT_R|CONFIRM,
1408         Id,
1409         Number,
1410         "w",Info);
1411   return 2;
1412 }
1413
1414 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1415 {
1416   word i, Info;
1417   word Reject;
1418   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1420   API_PARSE * ai;
1421     API_PARSE ai_parms[5];
1422   word ch=0;
1423
1424   if(!plci) {
1425     dbug(1,dprintf("connect_res(no plci)"));
1426     return 0;  /* no plci, no send */
1427   }
1428
1429   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430   for(i=0;i<5;i++) ai_parms[i].length = 0;
1431   ai = &parms[5];
1432   dbug(1,dprintf("ai->length=%d",ai->length));
1433
1434   if(ai->length)
1435   {
1436     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1437     {
1438       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1439       ch = 0;
1440       if(ai_parms[0].length)
1441       {
1442         ch = GET_WORD(ai_parms[0].info+1);
1443         dbug(1,dprintf("BCH-I=0x%x",ch));
1444       }
1445     }
1446   }
1447
1448   if(plci->State==INC_CON_CONNECTED_ALERT)
1449   {
1450     dbug(1,dprintf("Connected Alert Call_Res"));
1451     if (a->Info_Mask[appl->Id-1] & 0x200)
1452     {
1453     /* early B3 connect (CIP mask bit 9) no release after a disc */
1454       add_p(plci,LLI,"\x01\x01");
1455     }
1456     add_s(plci, CONN_NR, &parms[2]);
1457     add_s(plci, LLC, &parms[4]);
1458     add_ai(plci, &parms[5]);
1459     plci->State = INC_CON_ACCEPT;
1460     sig_req(plci, CALL_RES,0);
1461     return 1;
1462   }
1463   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465     dump_c_ind_mask (plci);
1466     Reject = GET_WORD(parms[0].info);
1467     dbug(1,dprintf("Reject=0x%x",Reject));
1468     if(Reject) 
1469     {
1470       if(c_ind_mask_empty (plci)) 
1471       {
1472         if((Reject&0xff00)==0x3400) 
1473         {
1474           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475           add_p(plci,ESC,esc_t);
1476           add_ai(plci, &parms[5]);
1477           sig_req(plci,REJECT,0);
1478         }      
1479         else if(Reject==1 || Reject>9) 
1480         {
1481           add_ai(plci, &parms[5]);
1482           sig_req(plci,HANGUP,0);
1483         }
1484         else 
1485         {
1486           esc_t[2] = cau_t[(Reject&0x000f)];
1487           add_p(plci,ESC,esc_t);
1488           add_ai(plci, &parms[5]);
1489           sig_req(plci,REJECT,0);
1490         }
1491         plci->appl = appl;
1492       }
1493       else 
1494       {
1495         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1496       }
1497     }
1498     else {
1499       plci->appl = appl;
1500       if(Id & EXT_CONTROLLER){
1501         if(AdvCodecSupport(a, plci, appl, 0)){
1502           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503           sig_req(plci,HANGUP,0);
1504           return 1;
1505         }
1506         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1507         {
1508           Info = add_b23(plci, &parms[1]);
1509           if (Info)
1510           {
1511             dbug(1,dprintf("connect_res(error from add_b23)"));
1512             sig_req(plci,HANGUP,0);
1513             return 1;
1514           }
1515           if(plci->adv_nl)
1516           {
1517             nl_req_ncci(plci, ASSIGN, 0);
1518           }
1519         }
1520       }
1521       else
1522       {
1523         plci->tel = 0;
1524         if(ch!=2)
1525         {
1526           Info = add_b23(plci, &parms[1]);
1527           if (Info)
1528           {
1529             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530             sig_req(plci,HANGUP,0);
1531             return 1;
1532           }
1533         }
1534         nl_req_ncci(plci, ASSIGN, 0);
1535       }
1536
1537       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1538       {
1539         api_save_msg(parms, "wsssss", &plci->saved_msg);
1540         plci->spoofed_msg = CALL_RES;
1541         plci->internal_command = BLOCK_PLCI;
1542         plci->command = 0;
1543         dbug(1,dprintf("Spoof"));
1544       }
1545       else
1546       {
1547         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548         if (a->Info_Mask[appl->Id-1] & 0x200)
1549         {
1550           /* early B3 connect (CIP mask bit 9) no release after a disc */
1551           add_p(plci,LLI,"\x01\x01");
1552         }
1553         add_s(plci, CONN_NR, &parms[2]);
1554         add_s(plci, LLC, &parms[4]);
1555         add_ai(plci, &parms[5]);
1556         plci->State = INC_CON_ACCEPT;
1557         sig_req(plci, CALL_RES,0);
1558       }
1559
1560       for(i=0; i<max_appl; i++) {
1561         if(test_c_ind_mask_bit (plci, i)) {
1562           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1563         }
1564       }
1565     }
1566   }
1567   return 1;
1568 }
1569
1570 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1571 {
1572   dbug(1,dprintf("connect_a_res"));
1573   return false;
1574 }
1575
1576 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1577 {
1578   word Info;
1579   word i;
1580
1581   dbug(1,dprintf("disconnect_req"));
1582
1583   Info = _WRONG_IDENTIFIER;
1584
1585   if(plci)
1586   {
1587     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1588     {
1589       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1590       plci->appl = appl;
1591       for(i=0; i<max_appl; i++)
1592       {
1593         if(test_c_ind_mask_bit (plci, i))
1594           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595       }
1596       plci->State = OUTG_DIS_PENDING;
1597     }
1598     if(plci->Sig.Id && plci->appl)
1599     {
1600       Info = 0;
1601         if(plci->Sig.Id!=0xff)
1602         {
1603           if(plci->State!=INC_DIS_PENDING)
1604           {
1605             add_ai(plci, &msg[0]);
1606             sig_req(plci,HANGUP,0);
1607             plci->State = OUTG_DIS_PENDING;
1608             return 1;
1609           }
1610         }
1611         else
1612         {
1613           if (plci->NL.Id && !plci->nl_remove_id)
1614           {
1615             mixer_remove (plci);
1616             nl_req_ncci(plci,REMOVE,0);
1617           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1618           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619           plci->State = INC_DIS_PENDING;
1620           }
1621           return 1;
1622         }
1623       }
1624     }
1625
1626   if(!appl)  return false;
1627   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1628   return false;
1629 }
1630
1631 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1632 {
1633   dbug(1,dprintf("disconnect_res"));
1634   if(plci)
1635   {
1636         /* clear ind mask bit, just in case of collsion of          */
1637         /* DISCONNECT_IND and CONNECT_RES                           */
1638     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1639     ncci_free_receive_buffers (plci, 0);
1640     if(plci_remove_check(plci))
1641     {
1642       return 0;
1643     }
1644     if(plci->State==INC_DIS_PENDING
1645     || plci->State==SUSPENDING) {
1646       if(c_ind_mask_empty (plci)) {
1647         if(plci->State!=SUSPENDING)plci->State = IDLE;
1648         dbug(1,dprintf("chs=%d",plci->channels));
1649         if(!plci->channels) {
1650           plci_remove(plci);
1651         }
1652       }
1653     }
1654   }
1655   return 0;
1656 }
1657
1658 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1659 {
1660   word Info;
1661   byte i;
1662
1663   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1664
1665   Info = _WRONG_IDENTIFIER;
1666   if(a) {
1667     Info = 0;
1668     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1669     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1670     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1671     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1672       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1673     }
1674
1675     /* check if external controller listen and switch listen on or off*/
1676     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1677       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1678         dummy_plci.State = IDLE;
1679         a->codec_listen[appl->Id-1] = &dummy_plci;
1680         a->TelOAD[0] = (byte)(parms[3].length);
1681         for(i=1;parms[3].length>=i && i<22;i++) {
1682           a->TelOAD[i] = parms[3].info[i];
1683         }
1684         a->TelOAD[i] = 0;
1685         a->TelOSA[0] = (byte)(parms[4].length);
1686         for(i=1;parms[4].length>=i && i<22;i++) {
1687           a->TelOSA[i] = parms[4].info[i];
1688         }
1689         a->TelOSA[i] = 0;
1690       }
1691       else Info = 0x2002; /* wrong controller, codec not supported */
1692     }
1693     else{               /* clear listen */
1694       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1695     }
1696   }
1697   sendf(appl,
1698         _LISTEN_R|CONFIRM,
1699         Id,
1700         Number,
1701         "w",Info);
1702
1703   if (a) listen_check(a);
1704   return false;
1705 }
1706
1707 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1708 {
1709   word i;
1710   API_PARSE * ai;
1711   PLCI   * rc_plci = NULL;
1712     API_PARSE ai_parms[5];
1713   word Info = 0;
1714
1715   dbug(1,dprintf("info_req"));
1716   for(i=0;i<5;i++) ai_parms[i].length = 0;
1717
1718   ai = &msg[1];
1719
1720   if(ai->length)
1721   {
1722     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1723     {
1724       dbug(1,dprintf("AddInfo wrong"));
1725       Info = _WRONG_MESSAGE_FORMAT;
1726     }
1727   }
1728   if(!a) Info = _WRONG_STATE;
1729
1730   if(!Info && plci)
1731   {                /* no fac, with CPN, or KEY */
1732     rc_plci = plci;
1733     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1734     {
1735       /* overlap sending option */
1736       dbug(1,dprintf("OvlSnd"));
1737       add_s(plci,CPN,&msg[0]);
1738       add_s(plci,KEY,&ai_parms[1]);
1739       sig_req(plci,INFO_REQ,0);
1740       send_req(plci);
1741       return false;
1742     }
1743
1744     if(plci->State && ai_parms[2].length)
1745     {
1746       /* User_Info option */
1747       dbug(1,dprintf("UUI"));
1748       add_s(plci,UUI,&ai_parms[2]);
1749       sig_req(plci,USER_DATA,0);
1750     }
1751     else if(plci->State && ai_parms[3].length)
1752     {
1753       /* Facility option */
1754       dbug(1,dprintf("FAC"));
1755       add_s(plci,CPN,&msg[0]);
1756       add_ai(plci, &msg[1]);
1757       sig_req(plci,FACILITY_REQ,0);
1758     }
1759     else
1760     {
1761       Info = _WRONG_STATE;
1762     }
1763   }
1764   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1765   {
1766     /* NCR_Facility option -> send UUI and Keypad too */
1767     dbug(1,dprintf("NCR_FAC"));
1768     if((i=get_plci(a)))
1769     {
1770       rc_plci = &a->plci[i-1];
1771       appl->NullCREnable  = true;
1772       rc_plci->internal_command = C_NCR_FAC_REQ;
1773       rc_plci->appl = appl;
1774       add_p(rc_plci,CAI,"\x01\x80");
1775       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1776       sig_req(rc_plci,ASSIGN,DSIG_ID);
1777       send_req(rc_plci);
1778     }
1779     else
1780     {
1781       Info = _OUT_OF_PLCI;
1782     }
1783
1784     if(!Info)
1785     {
1786       add_s(rc_plci,CPN,&msg[0]);
1787       add_ai(rc_plci, &msg[1]);
1788       sig_req(rc_plci,NCR_FACILITY,0);
1789       send_req(rc_plci);
1790       return false;
1791      /* for application controlled supplementary services    */
1792     }
1793   }
1794
1795   if (!rc_plci)
1796   {
1797     Info = _WRONG_MESSAGE_FORMAT;
1798   }
1799
1800   if(!Info)
1801   {
1802     send_req(rc_plci);
1803   }
1804   else
1805   {  /* appl is not assigned to a PLCI or error condition */
1806     dbug(1,dprintf("localInfoCon"));
1807     sendf(appl,
1808           _INFO_R|CONFIRM,
1809           Id,
1810           Number,
1811           "w",Info);
1812   }
1813   return false;
1814 }
1815
1816 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1817 {
1818   dbug(1,dprintf("info_res"));
1819   return false;
1820 }
1821
1822 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1823 {
1824   word Info;
1825   byte ret;
1826
1827   dbug(1,dprintf("alert_req"));
1828
1829   Info = _WRONG_IDENTIFIER;
1830   ret = false;
1831   if(plci) {
1832     Info = _ALERT_IGNORED;
1833     if(plci->State!=INC_CON_ALERT) {
1834       Info = _WRONG_STATE;
1835       if(plci->State==INC_CON_PENDING) {
1836         Info = 0;
1837         plci->State=INC_CON_ALERT;
1838         add_ai(plci, &msg[0]);
1839         sig_req(plci,CALL_ALERT,0);
1840         ret = 1;
1841       }
1842     }
1843   }
1844   sendf(appl,
1845         _ALERT_R|CONFIRM,
1846         Id,
1847         Number,
1848         "w",Info);
1849   return ret;
1850 }
1851
1852 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1853 {
1854   word Info = 0;
1855   word i    = 0;
1856
1857   word selector;
1858   word SSreq;
1859   long relatedPLCIvalue;
1860   DIVA_CAPI_ADAPTER   * relatedadapter;
1861   byte * SSparms  = "";
1862     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1863     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1864   API_PARSE * parms;
1865     API_PARSE ss_parms[11];
1866   PLCI   *rplci;
1867     byte cai[15];
1868   dword d;
1869     API_PARSE dummy;
1870
1871   dbug(1,dprintf("facility_req"));
1872   for(i=0;i<9;i++) ss_parms[i].length = 0;
1873
1874   parms = &msg[1];
1875
1876   if(!a)
1877   {
1878     dbug(1,dprintf("wrong Ctrl"));
1879     Info = _WRONG_IDENTIFIER;
1880   }
1881
1882   selector = GET_WORD(msg[0].info);
1883
1884   if(!Info)
1885   {
1886     switch(selector)
1887     {
1888       case SELECTOR_HANDSET:
1889         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1890         break;
1891
1892       case SELECTOR_SU_SERV:
1893         if(!msg[1].length)
1894         {
1895           Info = _WRONG_MESSAGE_FORMAT;
1896           break;
1897         }
1898         SSreq = GET_WORD(&(msg[1].info[1]));
1899         PUT_WORD(&RCparms[1],SSreq);
1900         SSparms = RCparms;
1901         switch(SSreq)
1902         {
1903           case S_GET_SUPPORTED_SERVICES:
1904             if((i=get_plci(a)))
1905             {
1906               rplci = &a->plci[i-1];
1907               rplci->appl = appl;
1908               add_p(rplci,CAI,"\x01\x80");
1909               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1910               sig_req(rplci,ASSIGN,DSIG_ID);
1911               send_req(rplci);
1912             }
1913             else
1914             {
1915               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1916               SSparms = (byte *)SSstruct;
1917               break;
1918             }
1919             rplci->internal_command = GETSERV_REQ_PEND;
1920             rplci->number = Number;
1921             rplci->appl = appl;
1922             sig_req(rplci,S_SUPPORTED,0);
1923             send_req(rplci);
1924             return false;
1925             break;
1926
1927           case S_LISTEN:
1928             if(parms->length==7)
1929             {
1930               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1931               {
1932                 dbug(1,dprintf("format wrong"));
1933                 Info = _WRONG_MESSAGE_FORMAT;
1934                 break;
1935               }
1936             }
1937             else
1938             {
1939               Info = _WRONG_MESSAGE_FORMAT;
1940               break;
1941             }
1942             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1943             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1944             {
1945               if((i=get_plci(a)))
1946               {
1947                 rplci = &a->plci[i-1];
1948                 rplci->appl = appl;
1949                 add_p(rplci,CAI,"\x01\x80");
1950                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1951                 sig_req(rplci,ASSIGN,DSIG_ID);
1952                 send_req(rplci);
1953               }
1954               else
1955               {
1956                 break;
1957               }
1958               rplci->internal_command = GET_MWI_STATE;
1959               rplci->number = Number;
1960               sig_req(rplci,MWI_POLL,0);
1961               send_req(rplci);
1962             }
1963             break;
1964
1965           case S_HOLD:
1966             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1967             if(plci && plci->State && plci->SuppState==IDLE)
1968             {
1969               plci->SuppState = HOLD_REQUEST;
1970               plci->command = C_HOLD_REQ;
1971               add_s(plci,CAI,&ss_parms[1]);
1972               sig_req(plci,CALL_HOLD,0);
1973               send_req(plci);
1974               return false;
1975             }
1976             else Info = 0x3010;                    /* wrong state           */
1977             break;
1978           case S_RETRIEVE:
1979             if(plci && plci->State && plci->SuppState==CALL_HELD)
1980             {
1981               if(Id & EXT_CONTROLLER)
1982               {
1983                 if(AdvCodecSupport(a, plci, appl, 0))
1984                 {
1985                   Info = 0x3010;                    /* wrong state           */
1986                   break;
1987                 }
1988               }
1989               else plci->tel = 0;
1990
1991               plci->SuppState = RETRIEVE_REQUEST;
1992               plci->command = C_RETRIEVE_REQ;
1993               if(plci->spoofed_msg==SPOOFING_REQUIRED)
1994               {
1995                 plci->spoofed_msg = CALL_RETRIEVE;
1996                 plci->internal_command = BLOCK_PLCI;
1997                 plci->command = 0;
1998                 dbug(1,dprintf("Spoof"));
1999                 return false;
2000               }
2001               else
2002               {
2003                 sig_req(plci,CALL_RETRIEVE,0);
2004                 send_req(plci);
2005                 return false;
2006               }
2007             }
2008             else Info = 0x3010;                    /* wrong state           */
2009             break;
2010           case S_SUSPEND:
2011             if(parms->length)
2012             {
2013               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2014               {
2015                 dbug(1,dprintf("format wrong"));
2016                 Info = _WRONG_MESSAGE_FORMAT;
2017                 break;
2018               }
2019             }
2020             if(plci && plci->State)
2021             {
2022               add_s(plci,CAI,&ss_parms[2]);
2023               plci->command = SUSPEND_REQ;
2024               sig_req(plci,SUSPEND,0);
2025               plci->State = SUSPENDING;
2026               send_req(plci);
2027             }
2028             else Info = 0x3010;                    /* wrong state           */
2029             break;
2030
2031           case S_RESUME:
2032             if(!(i=get_plci(a)) )
2033             {
2034               Info = _OUT_OF_PLCI;
2035               break;
2036             }
2037             rplci = &a->plci[i-1];
2038             rplci->appl = appl;
2039             rplci->number = Number;
2040             rplci->tel = 0;
2041             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2042             /* check 'external controller' bit for codec support */
2043             if(Id & EXT_CONTROLLER)
2044             {
2045               if(AdvCodecSupport(a, rplci, appl, 0) )
2046               {
2047                 rplci->Id = 0;
2048                 Info = 0x300A;
2049                 break;
2050               }
2051             }
2052             if(parms->length)
2053             {
2054               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2055               {
2056                 dbug(1,dprintf("format wrong"));
2057                 rplci->Id = 0;
2058                 Info = _WRONG_MESSAGE_FORMAT;
2059                 break;
2060               }
2061             }
2062             dummy.length = 0;
2063             dummy.info = "\x00";
2064             add_b1(rplci, &dummy, 0, 0);
2065             if (a->Info_Mask[appl->Id-1] & 0x200)
2066             {
2067               /* early B3 connect (CIP mask bit 9) no release after a disc */
2068               add_p(rplci,LLI,"\x01\x01");
2069             }
2070             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2071             sig_req(rplci,ASSIGN,DSIG_ID);
2072             send_req(rplci);
2073             add_s(rplci,CAI,&ss_parms[2]);
2074             rplci->command = RESUME_REQ;
2075             sig_req(rplci,RESUME,0);
2076             rplci->State = RESUMING;
2077             send_req(rplci);
2078             break;
2079
2080           case S_CONF_BEGIN: /* Request */
2081           case S_CONF_DROP:
2082           case S_CONF_ISOLATE:
2083           case S_CONF_REATTACH:
2084             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2085             {
2086               dbug(1,dprintf("format wrong"));
2087               Info = _WRONG_MESSAGE_FORMAT;
2088               break;
2089             }
2090             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2091             {
2092               d = GET_DWORD(ss_parms[2].info);     
2093               if(d>=0x80)
2094               {
2095                 dbug(1,dprintf("format wrong"));
2096                 Info = _WRONG_MESSAGE_FORMAT;
2097                 break;
2098               }
2099               plci->ptyState = (byte)SSreq;
2100               plci->command = 0;
2101               cai[0] = 2;
2102               switch(SSreq)
2103               {
2104               case S_CONF_BEGIN:
2105                   cai[1] = CONF_BEGIN;
2106                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2107                   break;
2108               case S_CONF_DROP:
2109                   cai[1] = CONF_DROP;
2110                   plci->internal_command = CONF_DROP_REQ_PEND;
2111                   break;
2112               case S_CONF_ISOLATE:
2113                   cai[1] = CONF_ISOLATE;
2114                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2115                   break;
2116               case S_CONF_REATTACH:
2117                   cai[1] = CONF_REATTACH;
2118                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2119                   break;
2120               }
2121               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2122               add_p(plci,CAI,cai);
2123               sig_req(plci,S_SERVICE,0);
2124               send_req(plci);
2125               return false;
2126             }
2127             else Info = 0x3010;                    /* wrong state           */
2128             break;
2129
2130           case S_ECT:
2131           case S_3PTY_BEGIN:
2132           case S_3PTY_END:
2133           case S_CONF_ADD:
2134             if(parms->length==7)
2135             {
2136               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2137               {
2138                 dbug(1,dprintf("format wrong"));
2139                 Info = _WRONG_MESSAGE_FORMAT;
2140                 break;
2141               }
2142             }
2143             else if(parms->length==8) /* workaround for the T-View-S */
2144             {
2145               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2146               {
2147                 dbug(1,dprintf("format wrong"));
2148                 Info = _WRONG_MESSAGE_FORMAT;
2149                 break;
2150               }
2151             }
2152             else
2153             {
2154               Info = _WRONG_MESSAGE_FORMAT;
2155               break;
2156             }
2157             if(!msg[1].length)
2158             {
2159               Info = _WRONG_MESSAGE_FORMAT;
2160               break;
2161             }
2162             if (!plci)
2163             {
2164               Info = _WRONG_IDENTIFIER;
2165               break;
2166             }
2167             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2168             relatedPLCIvalue &= 0x0000FFFF;
2169             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2170             /* controller starts with 0 up to (max_adapter - 1) */
2171             if (((relatedPLCIvalue & 0x7f) == 0)
2172              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2173              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2174             {
2175               if(SSreq==S_3PTY_END)
2176               {
2177                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2178                 rplci = plci;
2179               }
2180               else
2181               {
2182                 Info = 0x3010;                    /* wrong state           */
2183                 break;
2184               }
2185             }
2186             else
2187             {  
2188               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2189               relatedPLCIvalue >>=8;
2190               /* find PLCI PTR*/
2191               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2192               {
2193                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2194                 {
2195                   rplci = &relatedadapter->plci[i];
2196                 }
2197               }
2198               if(!rplci || !relatedPLCIvalue)
2199               {
2200                 if(SSreq==S_3PTY_END)
2201                 {
2202                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2203                   rplci = plci;
2204                 }
2205                 else
2206                 {
2207                   Info = 0x3010;                    /* wrong state           */
2208                   break;
2209                 }
2210               }
2211             }
2212 /*
2213             dbug(1,dprintf("rplci:%x",rplci));
2214             dbug(1,dprintf("plci:%x",plci));
2215             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2216             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2217             dbug(1,dprintf("SSreq:%x",SSreq));
2218             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2219             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2220             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2221 */
2222             /* send PTY/ECT req, cannot check all states because of US stuff */
2223             if( !rplci->internal_command && rplci->appl )
2224             {
2225               plci->command = 0;
2226               rplci->relatedPTYPLCI = plci;
2227               plci->relatedPTYPLCI = rplci;
2228               rplci->ptyState = (byte)SSreq;
2229               if(SSreq==S_ECT)
2230               {
2231                 rplci->internal_command = ECT_REQ_PEND;
2232                 cai[1] = ECT_EXECUTE;
2233
2234                 rplci->vswitchstate=0;
2235                 rplci->vsprot=0;
2236                 rplci->vsprotdialect=0;
2237                 plci->vswitchstate=0;
2238                 plci->vsprot=0;
2239                 plci->vsprotdialect=0;
2240
2241               }
2242               else if(SSreq==S_CONF_ADD)
2243               {
2244                 rplci->internal_command = CONF_ADD_REQ_PEND;
2245                 cai[1] = CONF_ADD;
2246               }
2247               else
2248               {
2249                 rplci->internal_command = PTY_REQ_PEND;
2250                 cai[1] = (byte)(SSreq-3);
2251               }
2252               rplci->number = Number;
2253               if(plci!=rplci) /* explicit invocation */
2254               {
2255                 cai[0] = 2;
2256                 cai[2] = plci->Sig.Id;
2257                 dbug(1,dprintf("explicit invocation"));
2258               }
2259               else
2260               {
2261                 dbug(1,dprintf("implicit invocation"));
2262                 cai[0] = 1;
2263               }
2264               add_p(rplci,CAI,cai);
2265               sig_req(rplci,S_SERVICE,0);
2266               send_req(rplci);
2267               return false;
2268             }
2269             else
2270             {
2271               dbug(0,dprintf("Wrong line"));
2272               Info = 0x3010;                    /* wrong state           */
2273               break;
2274             }
2275             break;
2276
2277           case S_CALL_DEFLECTION:
2278             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2279             {
2280               dbug(1,dprintf("format wrong"));
2281               Info = _WRONG_MESSAGE_FORMAT;
2282               break;
2283             }
2284             if (!plci)
2285             {
2286               Info = _WRONG_IDENTIFIER;
2287               break;
2288             }
2289             /* reuse unused screening indicator */
2290             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2291             plci->command = 0;
2292             plci->internal_command = CD_REQ_PEND;
2293             appl->CDEnable = true;
2294             cai[0] = 1;
2295             cai[1] = CALL_DEFLECTION;
2296             add_p(plci,CAI,cai);
2297             add_p(plci,CPN,ss_parms[3].info);
2298             sig_req(plci,S_SERVICE,0);
2299             send_req(plci);
2300             return false;
2301             break;
2302
2303           case S_CALL_FORWARDING_START:
2304             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2305             {
2306               dbug(1,dprintf("format wrong"));
2307               Info = _WRONG_MESSAGE_FORMAT;
2308               break;
2309             }
2310
2311             if((i=get_plci(a)))
2312             {
2313               rplci = &a->plci[i-1];
2314               rplci->appl = appl;
2315               add_p(rplci,CAI,"\x01\x80");
2316               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2317               sig_req(rplci,ASSIGN,DSIG_ID);
2318               send_req(rplci);
2319             }
2320             else
2321             {
2322               Info = _OUT_OF_PLCI;
2323               break;
2324             }
2325
2326             /* reuse unused screening indicator */
2327             rplci->internal_command = CF_START_PEND;
2328             rplci->appl = appl;
2329             rplci->number = Number;
2330             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2331             cai[0] = 2;
2332             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2333             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334             add_p(rplci,CAI,cai);
2335             add_p(rplci,OAD,ss_parms[5].info);
2336             add_p(rplci,CPN,ss_parms[6].info);
2337             sig_req(rplci,S_SERVICE,0);
2338             send_req(rplci);
2339             return false;
2340             break;
2341
2342           case S_INTERROGATE_DIVERSION:
2343           case S_INTERROGATE_NUMBERS:
2344           case S_CALL_FORWARDING_STOP:
2345           case S_CCBS_REQUEST:
2346           case S_CCBS_DEACTIVATE:
2347           case S_CCBS_INTERROGATE:
2348             switch(SSreq)
2349             {
2350             case S_INTERROGATE_NUMBERS:
2351                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2352                 {
2353                   dbug(0,dprintf("format wrong"));
2354                   Info = _WRONG_MESSAGE_FORMAT;
2355                 }
2356                 break;
2357             case S_CCBS_REQUEST:
2358             case S_CCBS_DEACTIVATE:
2359                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2360                 {
2361                   dbug(0,dprintf("format wrong"));
2362                   Info = _WRONG_MESSAGE_FORMAT;
2363                 }
2364                 break;
2365             case S_CCBS_INTERROGATE:
2366                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2367                 {
2368                   dbug(0,dprintf("format wrong"));
2369                   Info = _WRONG_MESSAGE_FORMAT;
2370                 }
2371                 break;
2372             default:
2373             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2374             {
2375               dbug(0,dprintf("format wrong"));
2376               Info = _WRONG_MESSAGE_FORMAT;
2377               break;
2378             }
2379                 break;
2380             }
2381
2382             if(Info) break;
2383             if((i=get_plci(a)))
2384             {
2385               rplci = &a->plci[i-1];
2386               switch(SSreq)
2387               {
2388                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2389                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2390                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2391                   break;
2392                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2393                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2394                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2395                   break;
2396                 case S_CALL_FORWARDING_STOP:
2397                   rplci->internal_command = CF_STOP_PEND;
2398                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2399                   break;
2400                 case S_CCBS_REQUEST:
2401                   cai[1] = CCBS_REQUEST;
2402                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2403                   break;
2404                 case S_CCBS_DEACTIVATE:
2405                   cai[1] = CCBS_DEACTIVATE;
2406                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2407                   break;
2408                 case S_CCBS_INTERROGATE:
2409                   cai[1] = CCBS_INTERROGATE;
2410                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2411                   break;
2412                 default:
2413                   cai[1] = 0;
2414                 break;
2415               }
2416               rplci->appl = appl;
2417               rplci->number = Number;
2418               add_p(rplci,CAI,"\x01\x80");
2419               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2420               sig_req(rplci,ASSIGN,DSIG_ID);
2421               send_req(rplci);
2422             }
2423             else
2424             {
2425               Info = _OUT_OF_PLCI;
2426               break;
2427             }
2428
2429             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2430             switch(SSreq)
2431             {
2432             case S_INTERROGATE_NUMBERS:
2433                 cai[0] = 1;
2434                 add_p(rplci,CAI,cai);
2435                 break;
2436             case S_CCBS_REQUEST:
2437             case S_CCBS_DEACTIVATE:
2438                 cai[0] = 3;
2439                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2440                 add_p(rplci,CAI,cai);
2441                 break;
2442             case S_CCBS_INTERROGATE:
2443                 cai[0] = 3;
2444                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2445                 add_p(rplci,CAI,cai);
2446                 add_p(rplci,OAD,ss_parms[4].info);
2447                 break;
2448             default:
2449             cai[0] = 2;
2450             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2451             add_p(rplci,CAI,cai);
2452             add_p(rplci,OAD,ss_parms[5].info);
2453                 break;
2454             }
2455                         
2456             sig_req(rplci,S_SERVICE,0);
2457             send_req(rplci);
2458             return false;
2459             break;
2460
2461           case S_MWI_ACTIVATE:
2462             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2463             {
2464               dbug(1,dprintf("format wrong"));
2465               Info = _WRONG_MESSAGE_FORMAT;
2466               break;
2467             }
2468             if(!plci)
2469             {                               
2470               if((i=get_plci(a)))
2471               {
2472                 rplci = &a->plci[i-1];
2473                 rplci->appl = appl;
2474                 rplci->cr_enquiry=true;
2475                 add_p(rplci,CAI,"\x01\x80");
2476                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2477                 sig_req(rplci,ASSIGN,DSIG_ID);
2478                 send_req(rplci);
2479               }
2480               else
2481               {
2482                 Info = _OUT_OF_PLCI;
2483                 break;
2484               }
2485             }
2486             else
2487             {
2488               rplci = plci;
2489               rplci->cr_enquiry=false;
2490             }
2491
2492             rplci->command = 0;
2493             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2494             rplci->appl = appl;
2495             rplci->number = Number;
2496
2497             cai[0] = 13;
2498             cai[1] = ACTIVATION_MWI; /* Function */
2499             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2500             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2501             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2502             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2503             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2504             add_p(rplci,CAI,cai);
2505             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2506             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2507             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2508             add_p(rplci,UID,ss_parms[10].info); /* Time */
2509             sig_req(rplci,S_SERVICE,0);
2510             send_req(rplci);
2511             return false;
2512
2513           case S_MWI_DEACTIVATE:
2514             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2515             {
2516               dbug(1,dprintf("format wrong"));
2517               Info = _WRONG_MESSAGE_FORMAT;
2518               break;
2519             }
2520             if(!plci)
2521             {                               
2522               if((i=get_plci(a)))
2523               {
2524                 rplci = &a->plci[i-1];
2525                 rplci->appl = appl;
2526                 rplci->cr_enquiry=true;
2527                 add_p(rplci,CAI,"\x01\x80");
2528                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2529                 sig_req(rplci,ASSIGN,DSIG_ID);
2530                 send_req(rplci);
2531               }
2532               else
2533               {
2534                 Info = _OUT_OF_PLCI;
2535                 break;
2536               }
2537             }
2538             else
2539             {
2540               rplci = plci;
2541               rplci->cr_enquiry=false;
2542             }
2543
2544             rplci->command = 0;
2545             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2546             rplci->appl = appl;
2547             rplci->number = Number;
2548
2549             cai[0] = 5;
2550             cai[1] = DEACTIVATION_MWI; /* Function */
2551             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2552             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2553             add_p(rplci,CAI,cai);
2554             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2555             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2556             sig_req(rplci,S_SERVICE,0);
2557             send_req(rplci);
2558             return false;
2559
2560           default:
2561             Info = 0x300E;  /* not supported */
2562             break;
2563         }
2564         break; /* case SELECTOR_SU_SERV: end */
2565
2566
2567       case SELECTOR_DTMF:
2568         return (dtmf_request (Id, Number, a, plci, appl, msg));
2569
2570
2571
2572       case SELECTOR_LINE_INTERCONNECT:
2573         return (mixer_request (Id, Number, a, plci, appl, msg));
2574
2575
2576
2577       case PRIV_SELECTOR_ECHO_CANCELLER:
2578         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2579         return (ec_request (Id, Number, a, plci, appl, msg));
2580
2581       case SELECTOR_ECHO_CANCELLER:
2582         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2583         return (ec_request (Id, Number, a, plci, appl, msg));
2584
2585
2586       case SELECTOR_V42BIS:
2587       default:
2588         Info = _FACILITY_NOT_SUPPORTED;
2589         break;
2590     } /* end of switch(selector) */
2591   }
2592
2593   dbug(1,dprintf("SendFacRc"));
2594   sendf(appl,
2595         _FACILITY_R|CONFIRM,
2596         Id,
2597         Number,
2598         "wws",Info,selector,SSparms);
2599   return false;
2600 }
2601
2602 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
2603 {
2604   dbug(1,dprintf("facility_res"));
2605   return false;
2606 }
2607
2608 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2609 {
2610   word Info = 0;
2611   byte req;
2612   byte len;
2613   word w;
2614   word fax_control_bits, fax_feature_bits, fax_info_change;
2615   API_PARSE * ncpi;
2616     byte pvc[2];
2617
2618     API_PARSE fax_parms[9];
2619   word i;
2620
2621
2622   dbug(1,dprintf("connect_b3_req"));
2623   if(plci)
2624   {
2625     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2626      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2627     {
2628       Info = _WRONG_STATE;
2629     }
2630     else
2631     {
2632       /* local reply if assign unsuccessfull
2633          or B3 protocol allows only one layer 3 connection
2634            and already connected
2635              or B2 protocol not any LAPD
2636                and connect_b3_req contradicts originate/answer direction */
2637       if (!plci->NL.Id
2638        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2639         && ((plci->channels != 0)
2640          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2641           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2642       {
2643         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2644                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2645         Info = _WRONG_STATE;
2646         sendf(appl,                                                        
2647               _CONNECT_B3_R|CONFIRM,
2648               Id,
2649               Number,
2650               "w",Info);
2651         return false;
2652       }
2653       plci->requested_options_conn = 0;
2654
2655       req = N_CONNECT;
2656       ncpi = &parms[0];
2657       if(plci->B3_prot==2 || plci->B3_prot==3)
2658       {
2659         if(ncpi->length>2)
2660         {
2661           /* check for PVC */
2662           if(ncpi->info[2] || ncpi->info[3])
2663           {
2664             pvc[0] = ncpi->info[3];
2665             pvc[1] = ncpi->info[2];
2666             add_d(plci,2,pvc);
2667             req = N_RESET;
2668           }
2669           else
2670           {
2671             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2672             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2673           }
2674         }
2675       }
2676       else if(plci->B3_prot==5)
2677       {
2678         if (plci->NL.Id && !plci->nl_remove_id)
2679         {
2680           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2681           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2682           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2683            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2684           {
2685             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2686             fax_info_change = false;
2687             if (ncpi->length >= 4)
2688             {
2689               w = GET_WORD(&ncpi->info[3]);
2690               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2691               {
2692                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2693                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2694                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2695                 fax_info_change = true;
2696               }
2697               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2698               if (w & 0x0002)  /* Fax-polling request */
2699                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2700               if ((w & 0x0004) /* Request to send / poll another document */
2701                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2702               {
2703                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2704               }
2705               if (ncpi->length >= 6)
2706               {
2707                 w = GET_WORD(&ncpi->info[5]);
2708                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2709                 {
2710                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2711                   fax_info_change = true;
2712                 }
2713
2714                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2715                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2716                 {
2717                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2718                 }
2719                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2720                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2721                 {
2722                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2723                 }
2724                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2725                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2726                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2727                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2728                 {
2729                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2730                     Info = _WRONG_MESSAGE_FORMAT;
2731                   else
2732                   {
2733                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2735       {
2736                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2737                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2738                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2739       }
2740                     w = fax_parms[4].length;
2741                     if (w > 20)
2742                       w = 20;
2743                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2744                     for (i = 0; i < w; i++)
2745                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2746                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2747                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2748                     w = fax_parms[5].length;
2749                     if (w > 20)
2750                       w = 20;
2751                     plci->fax_connect_info_buffer[len++] = (byte) w;
2752                     for (i = 0; i < w; i++)
2753                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2754                     w = fax_parms[6].length;
2755                     if (w > 20)
2756                       w = 20;
2757                     plci->fax_connect_info_buffer[len++] = (byte) w;
2758                     for (i = 0; i < w; i++)
2759                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2760                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2761                       & (1L << PRIVATE_FAX_NONSTANDARD))
2762       {
2763                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2764         {
2765                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2766                         plci->fax_connect_info_buffer[len++] = 0;
2767         }
2768                       else
2769                       {
2770           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2771             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2772    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2773           for (i = 0; i < fax_parms[7].length; i++)
2774      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2775                       }
2776                     }
2777                   }
2778                 }
2779                 else
2780                 {
2781                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2782                 }
2783                 fax_info_change = true;
2784
2785               }
2786               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2787               {
2788                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2789                 fax_info_change = true;
2790               }
2791             }
2792             if (Info == GOOD)
2793             {
2794               plci->fax_connect_info_length = len;
2795               if (fax_info_change)
2796               {
2797                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2798                 {
2799                   start_internal_command (Id, plci, fax_connect_info_command);
2800                   return false;
2801                 }
2802                 else
2803                 {
2804                   start_internal_command (Id, plci, fax_adjust_b23_command);
2805                   return false;
2806                 }
2807               }
2808             }
2809           }
2810           else  Info = _WRONG_STATE;
2811         }
2812         else  Info = _WRONG_STATE;
2813       }
2814
2815       else if (plci->B3_prot == B3_RTP)
2816       {
2817         plci->internal_req_buffer[0] = ncpi->length + 1;
2818         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2819         for (w = 0; w < ncpi->length; w++)
2820           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2821         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2822         return false;
2823       }
2824
2825       if(!Info)
2826       {
2827         nl_req_ncci(plci,req,0);
2828         return 1;
2829       }
2830     }
2831   }
2832   else Info = _WRONG_IDENTIFIER;
2833
2834   sendf(appl,
2835         _CONNECT_B3_R|CONFIRM,
2836         Id,
2837         Number,
2838         "w",Info);
2839   return false;
2840 }
2841
2842 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2843 {
2844   word ncci;
2845   API_PARSE * ncpi;
2846   byte req;
2847
2848   word w;
2849
2850
2851     API_PARSE fax_parms[9];
2852   word i;
2853   byte len;
2854
2855
2856   dbug(1,dprintf("connect_b3_res"));
2857
2858   ncci = (word)(Id>>16);
2859   if(plci && ncci) {
2860     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2861       if (GET_WORD (&parms[0].info[0]) != 0)
2862       {
2863         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2864         channel_request_xon (plci, a->ncci_ch[ncci]);
2865         channel_xmit_xon (plci);
2866         cleanup_ncci_data (plci, ncci);
2867         nl_req_ncci(plci,N_DISC,(byte)ncci);
2868         return 1;
2869       }
2870       a->ncci_state[ncci] = INC_ACT_PENDING;
2871
2872       req = N_CONNECT_ACK;
2873       ncpi = &parms[1];
2874       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2875       {
2876
2877         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2878           & (1L << PRIVATE_FAX_NONSTANDARD))
2879  {
2880    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2881     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2882     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2883    {
2884             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2885             if (plci->fax_connect_info_length < len)
2886             {
2887               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2888               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2889             }
2890             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2891             {
2892               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2893             }
2894             else
2895             {
2896               if (plci->fax_connect_info_length <= len)
2897                 plci->fax_connect_info_buffer[len] = 0;
2898               len += 1 + plci->fax_connect_info_buffer[len];
2899               if (plci->fax_connect_info_length <= len)
2900                 plci->fax_connect_info_buffer[len] = 0;
2901               len += 1 + plci->fax_connect_info_buffer[len];
2902               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2903                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2904               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2905               for (i = 0; i < fax_parms[7].length; i++)
2906                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2907             }
2908             plci->fax_connect_info_length = len;
2909             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2910             start_internal_command (Id, plci, fax_connect_ack_command);
2911      return false;
2912           }
2913         }
2914
2915         nl_req_ncci(plci,req,(byte)ncci);
2916         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2917          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2918         {
2919           if (plci->B3_prot == 4)
2920             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2921           else
2922             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2923           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2924         }
2925       }
2926
2927       else if (plci->B3_prot == B3_RTP)
2928       {
2929         plci->internal_req_buffer[0] = ncpi->length + 1;
2930         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2931         for (w = 0; w < ncpi->length; w++)
2932           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2933         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2934         return false;
2935       }
2936
2937       else
2938       {
2939         if(ncpi->length>2) {
2940           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2941           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2942         }
2943         nl_req_ncci(plci,req,(byte)ncci);
2944         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2945         if (plci->adjust_b_restore)
2946         {
2947           plci->adjust_b_restore = false;
2948           start_internal_command (Id, plci, adjust_b_restore);
2949         }
2950       }
2951       return 1;
2952     }
2953   }
2954   return false;
2955 }
2956
2957 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2958 {
2959   word ncci;
2960
2961   ncci = (word)(Id>>16);
2962   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2963
2964   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2965    && (plci->State != OUTG_DIS_PENDING))
2966   {
2967     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2968       a->ncci_state[ncci] = CONNECTED;
2969       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2970       channel_request_xon (plci, a->ncci_ch[ncci]);
2971       channel_xmit_xon (plci);
2972     }
2973   }
2974   return false;
2975 }
2976
2977 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2978 {
2979   word Info;
2980   word ncci;
2981   API_PARSE * ncpi;
2982
2983   dbug(1,dprintf("disconnect_b3_req"));
2984
2985   Info = _WRONG_IDENTIFIER;
2986   ncci = (word)(Id>>16);
2987   if (plci && ncci)
2988   {
2989     Info = _WRONG_STATE;
2990     if ((a->ncci_state[ncci] == CONNECTED)
2991      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2992      || (a->ncci_state[ncci] == INC_CON_PENDING)
2993      || (a->ncci_state[ncci] == INC_ACT_PENDING))
2994     {
2995       a->ncci_state[ncci] = OUTG_DIS_PENDING;
2996       channel_request_xon (plci, a->ncci_ch[ncci]);
2997       channel_xmit_xon (plci);
2998
2999       if (a->ncci[ncci].data_pending
3000        && ((plci->B3_prot == B3_TRANSPARENT)
3001         || (plci->B3_prot == B3_T30)
3002         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3003       {
3004         plci->send_disc = (byte)ncci;
3005         plci->command = 0;
3006         return false;
3007       }
3008       else
3009       {
3010         cleanup_ncci_data (plci, ncci);
3011
3012         if(plci->B3_prot==2 || plci->B3_prot==3)
3013         {
3014           ncpi = &parms[0];
3015           if(ncpi->length>3)
3016           {
3017             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3018           }
3019         }
3020         nl_req_ncci(plci,N_DISC,(byte)ncci);
3021       }
3022       return 1;
3023     }
3024   }
3025   sendf(appl,
3026         _DISCONNECT_B3_R|CONFIRM,
3027         Id,
3028         Number,
3029         "w",Info);
3030   return false;
3031 }
3032
3033 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3034 {
3035   word ncci;
3036   word i;
3037
3038   ncci = (word)(Id>>16);
3039   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3040   if(plci && ncci) {
3041     plci->requested_options_conn = 0;
3042     plci->fax_connect_info_length = 0;
3043     plci->ncpi_state = 0x00;
3044     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3045       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3046     {
3047       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3048     }
3049     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3050     if(i<MAX_CHANNELS_PER_PLCI) {
3051       if(plci->channels)plci->channels--;
3052       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3053       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3054
3055       ncci_free_receive_buffers (plci, ncci);
3056
3057       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3058         if(plci->State == SUSPENDING){
3059           sendf(plci->appl,
3060                 _FACILITY_I,
3061                 Id & 0xffffL,
3062                 0,
3063                 "ws", (word)3, "\x03\x04\x00\x00");
3064           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3065         }
3066         plci_remove(plci);
3067         plci->State=IDLE;
3068       }
3069     }
3070     else
3071     {
3072       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3073        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3074        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3075       {
3076         ncci_free_receive_buffers (plci, ncci);
3077
3078         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3079
3080         plci->adapter->ncci_state[ncci] = IDLE;
3081         start_internal_command (Id, plci, fax_disconnect_command);
3082         return 1;
3083       }
3084     }
3085   }
3086   return false;
3087 }
3088
3089 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3090 {
3091   NCCI   *ncci_ptr;
3092   DATA_B3_DESC   *data;
3093   word Info;
3094   word ncci;
3095   word i;
3096
3097   dbug(1,dprintf("data_b3_req"));
3098
3099   Info = _WRONG_IDENTIFIER;
3100   ncci = (word)(Id>>16);
3101   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3102
3103   if (plci && ncci)
3104   {
3105     Info = _WRONG_STATE;
3106     if ((a->ncci_state[ncci] == CONNECTED)
3107      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3108     {
3109         /* queue data */
3110       ncci_ptr = &(a->ncci[ncci]);
3111       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3112       if (i >= MAX_DATA_B3)
3113         i -= MAX_DATA_B3;
3114       data = &(ncci_ptr->DBuffer[i]);
3115       data->Number = Number;
3116       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3117        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3118       {
3119
3120         data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3121
3122       }
3123       else
3124         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3125       data->Length = GET_WORD(parms[1].info);
3126       data->Handle = GET_WORD(parms[2].info);
3127       data->Flags = GET_WORD(parms[3].info);
3128       (ncci_ptr->data_pending)++;
3129
3130         /* check for delivery confirmation */
3131       if (data->Flags & 0x0004)
3132       {
3133         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3134         if (i >= MAX_DATA_ACK)
3135           i -= MAX_DATA_ACK;
3136         ncci_ptr->DataAck[i].Number = data->Number;
3137         ncci_ptr->DataAck[i].Handle = data->Handle;
3138         (ncci_ptr->data_ack_pending)++;
3139       }
3140
3141       send_data(plci);
3142       return false;
3143     }
3144   }
3145   if (appl)
3146   {
3147     if (plci)
3148     {
3149       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3150        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3151       {
3152
3153         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3154
3155       }
3156     }
3157     sendf(appl,
3158           _DATA_B3_R|CONFIRM,
3159           Id,
3160           Number,
3161           "ww",GET_WORD(parms[2].info),Info);
3162   }
3163   return false;
3164 }
3165
3166 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3167 {
3168   word n;
3169   word ncci;
3170   word NCCIcode;
3171
3172   dbug(1,dprintf("data_b3_res"));
3173
3174   ncci = (word)(Id>>16);
3175   if(plci && ncci) {
3176     n = GET_WORD(parms[0].info);
3177     dbug(1,dprintf("free(%d)",n));
3178     NCCIcode = ncci | (((word) a->Id) << 8);
3179     if(n<appl->MaxBuffer &&
3180        appl->DataNCCI[n]==NCCIcode &&
3181        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3182       dbug(1,dprintf("found"));
3183       appl->DataNCCI[n] = 0;
3184
3185       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3186         channel_request_xon (plci, a->ncci_ch[ncci]);
3187       }
3188       channel_xmit_xon (plci);
3189
3190       if(appl->DataFlags[n] &4) {
3191         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3192         return 1;
3193       }
3194     }
3195   }
3196   return false;
3197 }
3198
3199 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3200 {
3201   word Info;
3202   word ncci;
3203
3204   dbug(1,dprintf("reset_b3_req"));
3205
3206   Info = _WRONG_IDENTIFIER;
3207   ncci = (word)(Id>>16);
3208   if(plci && ncci)
3209   {
3210     Info = _WRONG_STATE;
3211     switch (plci->B3_prot)
3212     {
3213     case B3_ISO8208:
3214     case B3_X25_DCE:
3215       if(a->ncci_state[ncci]==CONNECTED)
3216       {
3217         nl_req_ncci(plci,N_RESET,(byte)ncci);
3218         send_req(plci);
3219         Info = GOOD;
3220       }
3221       break;
3222     case B3_TRANSPARENT:
3223       if(a->ncci_state[ncci]==CONNECTED)
3224       {
3225         start_internal_command (Id, plci, reset_b3_command);
3226         Info = GOOD;
3227       }
3228       break;
3229     }
3230   }
3231   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3232   sendf(appl,
3233         _RESET_B3_R|CONFIRM,
3234         Id,
3235         Number,
3236         "w",Info);
3237   return false;
3238 }
3239
3240 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3241 {
3242   word ncci;
3243
3244   dbug(1,dprintf("reset_b3_res"));
3245
3246   ncci = (word)(Id>>16);
3247   if(plci && ncci) {
3248     switch (plci->B3_prot)
3249     {
3250     case B3_ISO8208:
3251     case B3_X25_DCE:
3252       if(a->ncci_state[ncci]==INC_RES_PENDING)
3253       {
3254         a->ncci_state[ncci] = CONNECTED;
3255         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3256         return true;
3257       }
3258     break;
3259     }
3260   }
3261   return false;
3262 }
3263
3264 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3265 {
3266   word ncci;
3267   API_PARSE * ncpi;
3268   byte req;
3269
3270   dbug(1,dprintf("connect_b3_t90_a_res"));
3271
3272   ncci = (word)(Id>>16);
3273   if(plci && ncci) {
3274     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3275       a->ncci_state[ncci] = CONNECTED;
3276     }
3277     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3278       a->ncci_state[ncci] = CONNECTED;
3279
3280       req = N_CONNECT_ACK;
3281
3282         /* parms[0]==0 for CAPI original message definition! */
3283       if(parms[0].info) {
3284         ncpi = &parms[1];
3285         if(ncpi->length>2) {
3286           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3287           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3288         }
3289       }
3290       nl_req_ncci(plci,req,(byte)ncci);
3291       return 1;
3292     }
3293   }
3294   return false;
3295 }
3296
3297
3298 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3299 {
3300   word Info=0;
3301   word i;
3302   byte tel;
3303     API_PARSE bp_parms[7];
3304
3305   if(!plci || !msg)
3306   {
3307     Info = _WRONG_IDENTIFIER;
3308   }
3309   else
3310   {
3311     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3312                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3313     dbug(1,dprintf("PlciState=0x%x",plci->State));
3314     for(i=0;i<7;i++) bp_parms[i].length = 0;
3315
3316     /* check if no channel is open, no B3 connected only */
3317     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3318      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3319     {
3320       Info = _WRONG_STATE;
3321     }
3322     /* check message format and fill bp_parms pointer */
3323     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3324     {
3325       Info = _WRONG_MESSAGE_FORMAT;
3326     }
3327     else
3328     {
3329       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3330       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3331         if(Id & EXT_CONTROLLER)
3332         {
3333           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3334           return 0;
3335         }
3336         plci->State=INC_CON_CONNECTED_ALERT;
3337         plci->appl = appl;
3338         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3339         dump_c_ind_mask (plci);
3340         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3341         {                         /* its quasi a connect        */
3342           if(test_c_ind_mask_bit (plci, i))
3343             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3344         }
3345       }
3346
3347       api_save_msg(msg, "s", &plci->saved_msg);
3348       tel = plci->tel;
3349       if(Id & EXT_CONTROLLER)
3350       {
3351         if(tel) /* external controller in use by this PLCI */
3352         {
3353           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3354           {
3355             dbug(1,dprintf("Ext_Ctrl in use 1"));
3356             Info = _WRONG_STATE;
3357           }
3358         }
3359         else  /* external controller NOT in use by this PLCI ? */
3360         {
3361           if(a->AdvSignalPLCI)
3362           {
3363             dbug(1,dprintf("Ext_Ctrl in use 2"));
3364             Info = _WRONG_STATE;
3365           }
3366           else /* activate the codec */
3367           {
3368             dbug(1,dprintf("Ext_Ctrl start"));
3369             if(AdvCodecSupport(a, plci, appl, 0) )
3370             {
3371               dbug(1,dprintf("Error in codec procedures"));
3372               Info = _WRONG_STATE;
3373             }
3374             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3375             {
3376               plci->spoofed_msg = AWAITING_SELECT_B;
3377               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3378               plci->command = 0;
3379               dbug(1,dprintf("continue if codec loaded"));
3380               return false;
3381             }
3382           }
3383         }
3384       }
3385       else /* external controller bit is OFF */
3386       {
3387         if(tel) /* external controller in use, need to switch off */
3388         {
3389           if(a->AdvSignalAppl==appl)
3390           {
3391             CodecIdCheck(a, plci);
3392             plci->tel = 0;
3393             plci->adv_nl = 0;
3394             dbug(1,dprintf("Ext_Ctrl disable"));
3395           }
3396           else
3397           {
3398             dbug(1,dprintf("Ext_Ctrl not requested"));
3399           }
3400         }
3401       }
3402       if (!Info)
3403       {
3404         if (plci->call_dir & CALL_DIR_OUT)
3405           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3406         else if (plci->call_dir & CALL_DIR_IN)
3407           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3408         start_internal_command (Id, plci, select_b_command);
3409         return false;
3410       }
3411     }
3412   }
3413   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3414   return false;
3415 }
3416
3417 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3418 {
3419   word command;
3420   word i;
3421   word ncci;
3422   API_PARSE * m;
3423     API_PARSE m_parms[5];
3424   word codec;
3425   byte req;
3426   byte ch;
3427   byte dir;
3428   static byte chi[2] = {0x01,0x00};
3429   static byte lli[2] = {0x01,0x00};
3430   static byte codec_cai[2] = {0x01,0x01};
3431   static byte null_msg = {0};
3432   static API_PARSE null_parms = { 0, &null_msg };
3433   PLCI   * v_plci;
3434   word Info=0;
3435
3436   dbug(1,dprintf("manufacturer_req"));
3437   for(i=0;i<5;i++) m_parms[i].length = 0;
3438
3439   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3440     Info = _WRONG_MESSAGE_FORMAT;
3441   }
3442   command = GET_WORD(parms[1].info);
3443   m = &parms[2];
3444   if (!Info)
3445   {
3446     switch(command) {
3447     case _DI_ASSIGN_PLCI:
3448       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3449         Info = _WRONG_MESSAGE_FORMAT;
3450         break;
3451       }
3452       codec = GET_WORD(m_parms[0].info);
3453       ch = m_parms[1].info[0];
3454       dir = m_parms[2].info[0];
3455       if((i=get_plci(a))) {
3456         plci = &a->plci[i-1];
3457         plci->appl = appl;
3458         plci->command = _MANUFACTURER_R;
3459         plci->m_command = command;
3460         plci->number = Number;
3461         plci->State = LOCAL_CONNECT;
3462         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3463         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3464
3465         if((ch==1 || ch==2) && (dir<=2)) {
3466           chi[1] = (byte)(0x80|ch);
3467           lli[1] = 0;
3468           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3469           switch(codec)
3470           {
3471           case 0:
3472             Info = add_b1(plci,&m_parms[3],0,0);
3473             break;
3474           case 1:
3475             add_p(plci,CAI,codec_cai);
3476             break;
3477           /* manual 'swich on' to the codec support without signalling */
3478           /* first 'assign plci' with this function, then use */
3479           case 2:
3480             if(AdvCodecSupport(a, plci, appl, 0) ) {
3481               Info = _RESOURCE_ERROR;
3482             }
3483             else {
3484               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3485               lli[1] = 0x10; /* local call codec stream */
3486             }
3487             break;
3488           }
3489
3490           plci->State = LOCAL_CONNECT;
3491           plci->manufacturer = true;
3492           plci->command = _MANUFACTURER_R;
3493           plci->m_command = command;
3494           plci->number = Number;
3495
3496           if(!Info)
3497           {
3498             add_p(plci,LLI,lli);
3499             add_p(plci,CHI,chi);
3500             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3501             sig_req(plci,ASSIGN,DSIG_ID);
3502
3503             if(!codec)
3504             {
3505               Info = add_b23(plci,&m_parms[3]);
3506               if(!Info)
3507               {
3508                 nl_req_ncci(plci,ASSIGN,0);
3509                 send_req(plci);
3510               }
3511             }
3512             if(!Info)
3513             {
3514               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3515               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3516               {
3517                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3518                 plci->spoofed_msg = AWAITING_MANUF_CON;
3519                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3520                 plci->command = 0;
3521                 send_req(plci);
3522                 return false;
3523               }
3524               if(dir==1) {
3525                 sig_req(plci,CALL_REQ,0);
3526               }
3527               else if(!dir){
3528                 sig_req(plci,LISTEN_REQ,0);
3529               }
3530               send_req(plci);
3531             }
3532             else
3533             {
3534               sendf(appl,
3535                     _MANUFACTURER_R|CONFIRM,
3536                     Id,
3537                     Number,
3538                     "dww",_DI_MANU_ID,command,Info);
3539               return 2;
3540             }
3541           }
3542         }
3543       }
3544       else  Info = _OUT_OF_PLCI;
3545       break;
3546
3547     case _DI_IDI_CTRL:
3548       if(!plci)
3549       {
3550         Info = _WRONG_IDENTIFIER;
3551         break;
3552       }
3553       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3554         Info = _WRONG_MESSAGE_FORMAT;
3555         break;
3556       }
3557       req = m_parms[0].info[0];
3558       plci->command = _MANUFACTURER_R;
3559       plci->m_command = command;
3560       plci->number = Number;
3561       if(req==CALL_REQ)
3562       {
3563         plci->b_channel = getChannel(&m_parms[1]);
3564         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3565         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3566         {
3567           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3568           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3569           plci->command = 0;
3570           break;
3571         }
3572       }
3573       else if(req==LAW_REQ)
3574       {
3575         plci->cr_enquiry = true;
3576       }
3577       add_ss(plci,FTY,&m_parms[1]);
3578       sig_req(plci,req,0);
3579       send_req(plci);
3580       if(req==HANGUP)
3581       {      
3582         if (plci->NL.Id && !plci->nl_remove_id)
3583         {
3584           if (plci->channels)
3585           {
3586             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3587             {
3588               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3589               {
3590                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3591                 cleanup_ncci_data (plci, ncci);
3592                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3593               }
3594             }
3595           }
3596           mixer_remove (plci);
3597           nl_req_ncci(plci,REMOVE,0);
3598           send_req(plci);
3599         }  
3600       }
3601       break;
3602
3603     case _DI_SIG_CTRL:
3604     /* signalling control for loop activation B-channel */
3605       if(!plci)
3606       {
3607         Info = _WRONG_IDENTIFIER;
3608         break;
3609       }
3610       if(m->length){
3611         plci->command = _MANUFACTURER_R;
3612         plci->number = Number;
3613         add_ss(plci,FTY,m);
3614         sig_req(plci,SIG_CTRL,0);
3615         send_req(plci);
3616       }
3617       else Info = _WRONG_MESSAGE_FORMAT;
3618       break;
3619
3620     case _DI_RXT_CTRL:
3621     /* activation control for receiver/transmitter B-channel */
3622       if(!plci)
3623       {
3624         Info = _WRONG_IDENTIFIER;
3625         break;
3626       }
3627       if(m->length){
3628         plci->command = _MANUFACTURER_R;
3629         plci->number = Number;
3630         add_ss(plci,FTY,m);
3631         sig_req(plci,DSP_CTRL,0);
3632         send_req(plci);
3633       }
3634       else Info = _WRONG_MESSAGE_FORMAT;
3635       break;
3636
3637     case _DI_ADV_CODEC:
3638     case _DI_DSP_CTRL:
3639       /* TEL_CTRL commands to support non standard adjustments: */
3640       /* Ring on/off, Handset micro volume, external micro vol. */
3641       /* handset+external speaker volume, receiver+transm. gain,*/
3642       /* handsfree on (hookinfo off), set mixer command         */
3643
3644       if(command == _DI_ADV_CODEC)
3645       {
3646         if(!a->AdvCodecPLCI) {
3647           Info = _WRONG_STATE;
3648           break;
3649         }
3650         v_plci = a->AdvCodecPLCI;
3651       }
3652       else
3653       {
3654         if (plci
3655          && (m->length >= 3)
3656          && (m->info[1] == 0x1c)
3657          && (m->info[2] >= 1))
3658         {
3659           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3660           {
3661             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3662             {
3663               Info = _WRONG_STATE;
3664               break;
3665             }
3666             a->adv_voice_coef_length = m->info[2] - 1;
3667             if (a->adv_voice_coef_length > m->length - 3)
3668               a->adv_voice_coef_length = (byte)(m->length - 3);
3669             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3670               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3671             for (i = 0; i < a->adv_voice_coef_length; i++)
3672               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3673             if (plci->B1_facilities & B1_FACILITY_VOICE)
3674               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3675             break;
3676           }
3677           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3678           {
3679             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3680             {
3681               Info = _FACILITY_NOT_SUPPORTED;
3682               break;
3683             }
3684
3685             plci->dtmf_parameter_length = m->info[2] - 1;
3686             if (plci->dtmf_parameter_length > m->length - 3)
3687               plci->dtmf_parameter_length = (byte)(m->length - 3);
3688             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3689               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3690             for (i = 0; i < plci->dtmf_parameter_length; i++)
3691               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3692             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3693               dtmf_parameter_write (plci);
3694             break;
3695
3696           }
3697         }
3698         v_plci = plci;
3699       }
3700
3701       if(!v_plci)
3702       {
3703         Info = _WRONG_IDENTIFIER;
3704         break;
3705       }
3706       if(m->length){
3707         add_ss(v_plci,FTY,m);
3708         sig_req(v_plci,TEL_CTRL,0);
3709         send_req(v_plci);
3710       }
3711       else Info = _WRONG_MESSAGE_FORMAT;
3712
3713       break;
3714
3715     case _DI_OPTIONS_REQUEST:
3716       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3717         Info = _WRONG_MESSAGE_FORMAT;
3718         break;
3719       }
3720       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3721       {
3722         Info = _FACILITY_NOT_SUPPORTED;
3723         break;
3724       }
3725       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3726       break;
3727
3728
3729
3730     default:
3731       Info = _WRONG_MESSAGE_FORMAT;
3732       break;
3733     }
3734   }
3735
3736   sendf(appl,
3737         _MANUFACTURER_R|CONFIRM,
3738         Id,
3739         Number,
3740         "dww",_DI_MANU_ID,command,Info);
3741   return false;
3742 }
3743
3744
3745 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3746 {
3747   word indication;
3748
3749     API_PARSE m_parms[3];
3750   API_PARSE *ncpi;
3751     API_PARSE fax_parms[9];
3752   word i;
3753   byte len;
3754
3755
3756   dbug(1,dprintf("manufacturer_res"));
3757
3758   if ((msg[0].length == 0)
3759    || (msg[1].length == 0)
3760    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3761   {
3762     return false;
3763   }
3764   indication = GET_WORD(msg[1].info);
3765   switch (indication)
3766   {
3767
3768   case _DI_NEGOTIATE_B3:
3769     if(!plci)
3770       break;
3771     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3772      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3773     {
3774       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3775       break;
3776     }
3777     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3778     {
3779       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3780       break;
3781     }
3782     ncpi = &m_parms[1];
3783     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3784     if (plci->fax_connect_info_length < len)
3785     {
3786       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3787       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3788     }
3789     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3790     {
3791       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3792     }
3793     else
3794     {
3795       if (plci->fax_connect_info_length <= len)
3796         plci->fax_connect_info_buffer[len] = 0;
3797       len += 1 + plci->fax_connect_info_buffer[len];
3798       if (plci->fax_connect_info_length <= len)
3799         plci->fax_connect_info_buffer[len] = 0;
3800       len += 1 + plci->fax_connect_info_buffer[len];
3801       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3802         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3803       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3804       for (i = 0; i < fax_parms[7].length; i++)
3805         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3806     }
3807     plci->fax_connect_info_length = len;
3808     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3809     start_internal_command (Id, plci, fax_edata_ack_command);
3810     break;
3811
3812   }
3813   return false;
3814 }
3815
3816 /*------------------------------------------------------------------*/
3817 /* IDI callback function                                            */
3818 /*------------------------------------------------------------------*/
3819
3820 void   callback(ENTITY   * e)
3821 {
3822   DIVA_CAPI_ADAPTER   * a;
3823   APPL   * appl;
3824   PLCI   * plci;
3825   CAPI_MSG   *m;
3826   word i, j;
3827   byte rc;
3828   byte ch;
3829   byte req;
3830   byte global_req;
3831   int no_cancel_rc;
3832
3833   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3834                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3835
3836   a = &(adapter[(byte)e->user[0]]);
3837   plci = &(a->plci[e->user[1]]);
3838   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3839
3840   /*
3841      If new protocol code and new XDI is used then CAPI should work
3842      fully in accordance with IDI cpec an look on callback field instead
3843      of Rc field for return codes.
3844    */
3845   if (((e->complete == 0xff) && no_cancel_rc) ||
3846       (e->Rc && !no_cancel_rc)) {
3847     rc = e->Rc;
3848     ch = e->RcCh;
3849     req = e->Req;
3850     e->Rc = 0;
3851
3852     if (e->user[0] & 0x8000)
3853     {
3854       /*
3855          If REMOVE request was sent then we have to wait until
3856          return code with Id set to zero arrives.
3857          All other return codes should be ignored.
3858          */
3859       if (req == REMOVE)
3860       {
3861         if (e->Id)
3862         {
3863           dbug(1,dprintf("cancel RC in REMOVE state"));
3864           return;
3865         }
3866         channel_flow_control_remove (plci);
3867         for (i = 0; i < 256; i++)
3868         {
3869           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3870             a->FlowControlIdTable[i] = 0;
3871         }
3872         plci->nl_remove_id = 0;
3873         if (plci->rx_dma_descriptor > 0) {
3874           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3875           plci->rx_dma_descriptor = 0;
3876         }
3877       }
3878       if (rc == OK_FC)
3879       {
3880         a->FlowControlIdTable[ch] = e->Id;
3881         a->FlowControlSkipTable[ch] = 0;
3882
3883         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3884         a->ch_flow_plci[ch] = plci->Id;
3885         plci->nl_req = 0;
3886       }
3887       else
3888       {
3889         /*
3890           Cancel return codes self, if feature was requested
3891           */
3892         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3893           a->FlowControlIdTable[ch] = 0;
3894           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3895             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3896             return;
3897           }
3898         }
3899
3900         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3901         {
3902           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3903           if (ch == e->ReqCh)
3904             plci->nl_req = 0;
3905         }
3906         else
3907           plci->nl_req = 0;
3908       }
3909       if (plci->nl_req)
3910         control_rc (plci, 0, rc, ch, 0, true);
3911       else
3912       {
3913         if (req == N_XON)
3914         {
3915           channel_x_on (plci, ch);
3916           if (plci->internal_command)
3917             control_rc (plci, req, rc, ch, 0, true);
3918         }
3919         else
3920         {
3921           if (plci->nl_global_req)
3922           {
3923             global_req = plci->nl_global_req;
3924             plci->nl_global_req = 0;
3925             if (rc != ASSIGN_OK) {
3926               e->Id = 0;
3927               if (plci->rx_dma_descriptor > 0) {
3928                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3929                 plci->rx_dma_descriptor = 0;
3930               }
3931             }
3932             channel_xmit_xon (plci);
3933             control_rc (plci, 0, rc, ch, global_req, true);
3934           }
3935           else if (plci->data_sent)
3936           {
3937             channel_xmit_xon (plci);
3938             plci->data_sent = false;
3939             plci->NL.XNum = 1;
3940             data_rc (plci, ch);
3941             if (plci->internal_command)
3942               control_rc (plci, req, rc, ch, 0, true);
3943           }
3944           else
3945           {
3946             channel_xmit_xon (plci);
3947             control_rc (plci, req, rc, ch, 0, true);
3948           }
3949         }
3950       }
3951     }
3952     else
3953     {
3954       /*
3955          If REMOVE request was sent then we have to wait until
3956          return code with Id set to zero arrives.
3957          All other return codes should be ignored.
3958          */
3959       if (req == REMOVE)
3960       {
3961         if (e->Id)
3962         {
3963           dbug(1,dprintf("cancel RC in REMOVE state"));
3964           return;
3965         }
3966         plci->sig_remove_id = 0;
3967       }
3968       plci->sig_req = 0;
3969       if (plci->sig_global_req)
3970       {
3971         global_req = plci->sig_global_req;
3972         plci->sig_global_req = 0;
3973         if (rc != ASSIGN_OK)
3974           e->Id = 0;
3975         channel_xmit_xon (plci);
3976         control_rc (plci, 0, rc, ch, global_req, false);
3977       }
3978       else
3979       {
3980         channel_xmit_xon (plci);
3981         control_rc (plci, req, rc, ch, 0, false);
3982       }
3983     }
3984     /*
3985       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3986       same callback. Also if new XDI and protocol code used then jump
3987       direct to finish.
3988       */
3989     if (no_cancel_rc) {
3990       channel_xmit_xon(plci);
3991       goto capi_callback_suffix;
3992     }
3993   }
3994
3995   channel_xmit_xon(plci);
3996
3997   if (e->Ind) {
3998     if (e->user[0] &0x8000) {
3999       byte Ind = e->Ind & 0x0f;
4000       byte Ch = e->IndCh;
4001       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4002           (a->ch_flow_plci[Ch] == plci->Id)) {
4003         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4004           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4005         }
4006         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4007       }
4008       nl_ind(plci);
4009       if ((e->RNR != 1) &&
4010           (a->ch_flow_plci[Ch] == plci->Id) &&
4011           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4012         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4013         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4014       }
4015     } else {
4016       sig_ind(plci);
4017     }
4018     e->Ind = 0;
4019   }
4020
4021 capi_callback_suffix:
4022
4023   while (!plci->req_in
4024    && !plci->internal_command
4025    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4026   {
4027     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4028
4029     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4030
4031     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4032     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4033     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4034       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4035     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4036     {
4037       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4038       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4039     }
4040     else
4041     {
4042       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4043     }
4044     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4045     {
4046       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4047       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4048     }
4049     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4050     {
4051       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4052       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4053     }
4054     i = api_put (appl, m);
4055     if (i != 0)
4056     {
4057       if (m->header.command == _DATA_B3_R)
4058
4059         TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4060
4061       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4062       break;
4063     }
4064
4065     if (plci->li_notify_update)
4066     {
4067       plci->li_notify_update = false;
4068       mixer_notify_update (plci, false);
4069     }
4070
4071   }
4072   send_data(plci);
4073   send_req(plci);
4074 }
4075
4076
4077 void control_rc(PLCI   * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4078 {
4079   dword Id;
4080   dword rId;
4081   word Number;
4082   word Info=0;
4083   word i;
4084   word ncci;
4085   DIVA_CAPI_ADAPTER   * a;
4086   APPL   * appl;
4087   PLCI   * rplci;
4088     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4089     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4090
4091   if (!plci) {
4092     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4093     return;
4094   }
4095   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4096   if(plci->req_in!=plci->req_out)
4097   {
4098     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4099     {
4100       dbug(1,dprintf("req_1return"));
4101       return;
4102     }
4103     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4104   }
4105   plci->req_in = plci->req_in_start = plci->req_out = 0;
4106   dbug(1,dprintf("control_rc"));
4107
4108   appl = plci->appl;
4109   a = plci->adapter;
4110   ncci = a->ch_ncci[ch];
4111   if(appl)
4112   {
4113     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4114     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4115     Number = plci->number;
4116     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));
4117     dbug(1,dprintf("channels=0x%x",plci->channels));
4118     if (plci_remove_check(plci))
4119       return;
4120     if(req==REMOVE && rc==ASSIGN_OK)
4121     {
4122       sig_req(plci,HANGUP,0);
4123       sig_req(plci,REMOVE,0);
4124       send_req(plci);
4125     }
4126     if(plci->command)
4127     {
4128       switch(plci->command)
4129       {
4130       case C_HOLD_REQ:
4131         dbug(1,dprintf("HoldRC=0x%x",rc));
4132         SSparms[1] = (byte)S_HOLD;
4133         if(rc!=OK)
4134         {
4135           plci->SuppState = IDLE;
4136           Info = 0x2001;
4137         }
4138         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4139         break;
4140
4141       case C_RETRIEVE_REQ:
4142         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4143         SSparms[1] = (byte)S_RETRIEVE;
4144         if(rc!=OK)
4145         {
4146           plci->SuppState = CALL_HELD;
4147           Info = 0x2001;
4148         }
4149         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4150         break;
4151
4152       case _INFO_R:
4153         dbug(1,dprintf("InfoRC=0x%x",rc));
4154         if(rc!=OK) Info=_WRONG_STATE;
4155         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4156         break;
4157
4158       case _CONNECT_R:
4159         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4160         if (plci->State == INC_DIS_PENDING)
4161           break;
4162         if(plci->Sig.Id!=0xff)
4163         {
4164           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4165            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4166           {
4167             dbug(1,dprintf("No more IDs/Call_Req failed"));
4168             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4169             plci_remove(plci);
4170             plci->State = IDLE;
4171             break;
4172           }
4173           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4174           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4175         }
4176         else /* D-ch activation */
4177         {
4178           if (rc != ASSIGN_OK)
4179           {
4180             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4181             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4182             plci_remove(plci);
4183             plci->State = IDLE;
4184             break;
4185           }
4186           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4187           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4188           plci->State = INC_ACT_PENDING;
4189         }
4190         break;
4191
4192       case _CONNECT_I|RESPONSE:
4193         if (plci->State != INC_DIS_PENDING)
4194           plci->State = INC_CON_ACCEPT;
4195         break;
4196
4197       case _DISCONNECT_R:
4198         if (plci->State == INC_DIS_PENDING)
4199           break;
4200         if(plci->Sig.Id!=0xff)
4201         {
4202           plci->State = OUTG_DIS_PENDING;
4203           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4204         }
4205         break;
4206
4207       case SUSPEND_REQ:
4208         break;
4209
4210       case RESUME_REQ:
4211         break;
4212
4213       case _CONNECT_B3_R:
4214         if(rc!=OK)
4215         {
4216           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4217           break;
4218         }
4219         ncci = get_ncci (plci, ch, 0);
4220         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4221         plci->channels++;
4222         if(req==N_RESET)
4223         {
4224           a->ncci_state[ncci] = INC_ACT_PENDING;
4225           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4226           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4227         }
4228         else
4229         {
4230           a->ncci_state[ncci] = OUTG_CON_PENDING;
4231           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4232         }
4233         break;
4234
4235       case _CONNECT_B3_I|RESPONSE:
4236         break;
4237
4238       case _RESET_B3_R:
4239 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4240         break;
4241
4242       case _DISCONNECT_B3_R:
4243         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4244         break;
4245
4246       case _MANUFACTURER_R:
4247         break;
4248
4249       case PERM_LIST_REQ:
4250         if(rc!=OK)
4251         {
4252           Info = _WRONG_IDENTIFIER;
4253           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4254           plci_remove(plci);
4255         }
4256         else
4257           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4258         break;
4259
4260       default:
4261         break;
4262       }
4263       plci->command = 0;
4264     }
4265     else if (plci->internal_command)
4266     {
4267       switch(plci->internal_command)
4268       {
4269       case BLOCK_PLCI:
4270         return;
4271
4272       case GET_MWI_STATE:
4273         if(rc==OK) /* command supported, wait for indication */
4274         {
4275           return;
4276         }
4277         plci_remove(plci);
4278         break;
4279
4280         /* Get Supported Services */
4281       case GETSERV_REQ_PEND:
4282         if(rc==OK) /* command supported, wait for indication */
4283         {
4284           break;
4285         }
4286         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4287         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4288         plci_remove(plci);
4289         break;
4290
4291       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4292       case INTERR_NUMBERS_REQ_PEND:
4293       case CF_START_PEND:                  /* Call Forwarding Start pending */
4294       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4295       case CCBS_REQUEST_REQ_PEND:
4296       case CCBS_DEACTIVATE_REQ_PEND:
4297       case CCBS_INTERROGATE_REQ_PEND:
4298         switch(plci->internal_command)
4299         {
4300           case INTERR_DIVERSION_REQ_PEND:
4301             SSparms[1] = S_INTERROGATE_DIVERSION;
4302             break;
4303           case INTERR_NUMBERS_REQ_PEND:
4304             SSparms[1] = S_INTERROGATE_NUMBERS;
4305             break;
4306           case CF_START_PEND:
4307             SSparms[1] = S_CALL_FORWARDING_START;
4308             break;
4309           case CF_STOP_PEND:
4310             SSparms[1] = S_CALL_FORWARDING_STOP;
4311             break;
4312           case CCBS_REQUEST_REQ_PEND:
4313             SSparms[1] = S_CCBS_REQUEST;
4314             break;
4315           case CCBS_DEACTIVATE_REQ_PEND:
4316             SSparms[1] = S_CCBS_DEACTIVATE;
4317             break;
4318           case CCBS_INTERROGATE_REQ_PEND:
4319             SSparms[1] = S_CCBS_INTERROGATE;
4320             break;
4321         }
4322         if(global_req==ASSIGN)
4323         {
4324           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4325           return;
4326         }
4327         if(!plci->appl) break;
4328         if(rc==ISDN_GUARD_REJ)
4329         {
4330           Info = _CAPI_GUARD_ERROR;
4331         }
4332         else if(rc!=OK)
4333         {
4334           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4335         }
4336         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4337               plci->number,"wws",Info,(word)3,SSparms);
4338         if(Info) plci_remove(plci);
4339         break;
4340
4341         /* 3pty conference pending */
4342       case PTY_REQ_PEND:
4343         if(!plci->relatedPTYPLCI) break;
4344         rplci = plci->relatedPTYPLCI;
4345         SSparms[1] = plci->ptyState;
4346         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4347         if(rplci->tel) rId|=EXT_CONTROLLER;
4348         if(rc!=OK)
4349         {
4350           Info = 0x300E; /* not supported */
4351           plci->relatedPTYPLCI = NULL;
4352           plci->ptyState = 0;
4353         }
4354         sendf(rplci->appl,
4355               _FACILITY_R|CONFIRM,
4356               rId,
4357               plci->number,
4358               "wws",Info,(word)3,SSparms);
4359         break;
4360
4361         /* Explicit Call Transfer pending */
4362       case ECT_REQ_PEND:
4363         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4364         if(!plci->relatedPTYPLCI) break;
4365         rplci = plci->relatedPTYPLCI;
4366         SSparms[1] = S_ECT;
4367         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4368         if(rplci->tel) rId|=EXT_CONTROLLER;
4369         if(rc!=OK)
4370         {
4371           Info = 0x300E; /* not supported */
4372           plci->relatedPTYPLCI = NULL;
4373           plci->ptyState = 0;
4374         }
4375         sendf(rplci->appl,
4376               _FACILITY_R|CONFIRM,
4377               rId,
4378               plci->number,
4379               "wws",Info,(word)3,SSparms);
4380         break;
4381
4382       case _MANUFACTURER_R:
4383         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4384         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4385         {
4386           dbug(1,dprintf("No more IDs"));
4387           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4388           plci_remove(plci);  /* after codec init, internal codec commands pending */
4389         }
4390         break;
4391
4392       case _CONNECT_R:
4393         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4394         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4395         {
4396           dbug(1,dprintf("No more IDs"));
4397           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4398           plci_remove(plci);  /* after codec init, internal codec commands pending */
4399         }
4400         break;
4401
4402       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4403         return;
4404
4405       case PERM_COD_CALL:
4406         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4407         plci->internal_command = PERM_COD_CONN_PEND;
4408         return;
4409
4410       case PERM_COD_ASSIGN:
4411         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4412         if(rc!=ASSIGN_OK) break;
4413         sig_req(plci,CALL_REQ,0);
4414         send_req(plci);
4415         plci->internal_command = PERM_COD_CALL;
4416         return;
4417
4418         /* Null Call Reference Request pending */
4419       case C_NCR_FAC_REQ:
4420         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4421         if(global_req==ASSIGN)
4422         {
4423           if(rc==ASSIGN_OK)
4424           {
4425             return;
4426           }
4427           else
4428           {
4429             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4430             appl->NullCREnable = false;
4431             plci_remove(plci);
4432           }
4433         }
4434         else if(req==NCR_FACILITY)
4435         {
4436           if(rc==OK)
4437           {
4438             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4439           }
4440           else
4441           {
4442             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4443             appl->NullCREnable = false;
4444           }
4445           plci_remove(plci);
4446         }
4447         break;
4448
4449       case HOOK_ON_REQ:
4450         if(plci->channels)
4451         {
4452           if(a->ncci_state[ncci]==CONNECTED)
4453           {
4454             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4455             cleanup_ncci_data (plci, ncci);
4456             nl_req_ncci(plci,N_DISC,(byte)ncci);
4457           }
4458           break;
4459         }
4460         break;
4461
4462       case HOOK_OFF_REQ:
4463         if (plci->State == INC_DIS_PENDING)
4464           break;
4465         sig_req(plci,CALL_REQ,0);
4466         send_req(plci);
4467         plci->State=OUTG_CON_PENDING;
4468         break;
4469
4470
4471       case MWI_ACTIVATE_REQ_PEND:
4472       case MWI_DEACTIVATE_REQ_PEND:
4473         if(global_req == ASSIGN && rc==ASSIGN_OK)
4474         {
4475           dbug(1,dprintf("MWI_REQ assigned"));
4476           return;
4477         }
4478         else if(rc!=OK)
4479         {                 
4480           if(rc==WRONG_IE)
4481           {
4482             Info = 0x2007; /* Illegal message parameter coding */
4483             dbug(1,dprintf("MWI_REQ invalid parameter"));
4484           }
4485           else
4486           {
4487             Info = 0x300B; /* not supported */                      
4488             dbug(1,dprintf("MWI_REQ not supported"));
4489           }
4490           /* 0x3010: Request not allowed in this state */
4491           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4492                     
4493         }
4494         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4495         {
4496           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4497         }
4498         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4499
4500         if(plci->cr_enquiry)
4501         {
4502           sendf(plci->appl,
4503                 _FACILITY_R|CONFIRM,
4504                 Id&0xf,
4505                 plci->number,
4506                 "wws",Info,(word)3,SSparms);
4507           if(rc!=OK) plci_remove(plci);
4508         }
4509         else
4510         {
4511           sendf(plci->appl,
4512                 _FACILITY_R|CONFIRM,
4513                 Id,
4514                 plci->number,
4515                 "wws",Info,(word)3,SSparms);
4516         }
4517         break;
4518
4519       case CONF_BEGIN_REQ_PEND:
4520       case CONF_ADD_REQ_PEND:
4521       case CONF_SPLIT_REQ_PEND:
4522       case CONF_DROP_REQ_PEND:
4523       case CONF_ISOLATE_REQ_PEND:
4524       case CONF_REATTACH_REQ_PEND:
4525         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4526         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4527         rplci = plci;
4528         rId = Id;
4529         switch(plci->internal_command)
4530         {
4531           case CONF_BEGIN_REQ_PEND:
4532             SSparms[1] = S_CONF_BEGIN;
4533             break;
4534           case CONF_ADD_REQ_PEND:
4535             SSparms[1] = S_CONF_ADD;
4536             rplci = plci->relatedPTYPLCI;
4537             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4538             break;
4539           case CONF_SPLIT_REQ_PEND:
4540             SSparms[1] = S_CONF_SPLIT;
4541             break;
4542           case CONF_DROP_REQ_PEND:
4543             SSparms[1] = S_CONF_DROP;
4544             break;
4545           case CONF_ISOLATE_REQ_PEND:
4546             SSparms[1] = S_CONF_ISOLATE;
4547             break;
4548           case CONF_REATTACH_REQ_PEND:
4549             SSparms[1] = S_CONF_REATTACH;
4550             break;
4551         }
4552         
4553         if(rc!=OK)
4554         {
4555           Info = 0x300E; /* not supported */
4556           plci->relatedPTYPLCI = NULL;
4557           plci->ptyState = 0;
4558         }
4559         sendf(rplci->appl,
4560               _FACILITY_R|CONFIRM,
4561               rId,
4562               plci->number,
4563               "wws",Info,(word)3,SSparms);
4564         break;
4565
4566       case VSWITCH_REQ_PEND:
4567         if(rc!=OK)
4568         {
4569           if(plci->relatedPTYPLCI)
4570           {
4571             plci->relatedPTYPLCI->vswitchstate=0;
4572             plci->relatedPTYPLCI->vsprot=0;
4573             plci->relatedPTYPLCI->vsprotdialect=0;    
4574           }
4575           plci->vswitchstate=0;
4576           plci->vsprot=0;
4577           plci->vsprotdialect=0;
4578         }
4579         else
4580         {
4581           if(plci->relatedPTYPLCI &&
4582              plci->vswitchstate==1 &&
4583              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4584             plci->vswitchstate=3;
4585         }
4586         break;
4587
4588   /* Call Deflection Request pending (SSCT) */
4589       case CD_REQ_PEND:
4590         SSparms[1] = S_CALL_DEFLECTION;
4591         if(rc!=OK)
4592         {
4593           Info = 0x300E; /* not supported */
4594           plci->appl->CDEnable = 0;
4595         }  
4596         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4597           plci->number,"wws",Info,(word)3,SSparms);
4598         break;
4599
4600       case RTP_CONNECT_B3_REQ_COMMAND_2:
4601         if (rc == OK)
4602         {
4603           ncci = get_ncci (plci, ch, 0);
4604           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4605           plci->channels++;
4606           a->ncci_state[ncci] = OUTG_CON_PENDING;
4607         }
4608
4609       default:
4610         if (plci->internal_command_queue[0])
4611         {
4612           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4613           if (plci->internal_command)
4614             return;
4615         }
4616         break;
4617       }
4618       next_internal_command (Id, plci);
4619     }
4620   }
4621   else /* appl==0 */
4622   {
4623     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4624     if(plci->tel) Id|=EXT_CONTROLLER;
4625
4626     switch(plci->internal_command)
4627     {
4628     case BLOCK_PLCI:
4629       return;
4630
4631     case START_L1_SIG_ASSIGN_PEND:
4632     case REM_L1_SIG_ASSIGN_PEND:
4633       if(global_req == ASSIGN)
4634       {
4635         break;
4636       }
4637       else
4638       {
4639         dbug(1,dprintf("***L1 Req rem PLCI"));
4640         plci->internal_command = 0;
4641         sig_req(plci,REMOVE,0);
4642         send_req(plci);
4643       }
4644       break;
4645
4646       /* Call Deflection Request pending, just no appl ptr assigned */
4647     case CD_REQ_PEND:
4648       SSparms[1] = S_CALL_DEFLECTION;
4649       if(rc!=OK)
4650       {
4651         Info = 0x300E; /* not supported */
4652       }
4653       for(i=0; i<max_appl; i++)
4654       {
4655         if(application[i].CDEnable)
4656         {
4657           if(!application[i].Id) application[i].CDEnable = 0;
4658           else
4659           {
4660             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4661                   plci->number,"wws",Info,(word)3,SSparms);
4662             if(Info) application[i].CDEnable = 0;
4663           }
4664         }
4665       }
4666       plci->internal_command = 0;
4667       break;
4668
4669     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4670       return;
4671
4672     case PERM_COD_CALL:
4673       plci->internal_command = PERM_COD_CONN_PEND;
4674       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4675       return;
4676
4677     case PERM_COD_ASSIGN:
4678       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4679       plci->internal_command = 0;
4680       if(rc!=ASSIGN_OK) break;
4681       plci->internal_command = PERM_COD_CALL;
4682       sig_req(plci,CALL_REQ,0);
4683       send_req(plci);
4684       return;
4685
4686     case LISTEN_SIG_ASSIGN_PEND:
4687       if(rc == ASSIGN_OK)
4688       {
4689         plci->internal_command = 0;
4690         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4691         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4692         sig_req(plci,INDICATE_REQ,0);
4693         send_req(plci);
4694       }
4695       else
4696       {
4697         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4698         a->listen_active--;
4699         plci_remove(plci);
4700         plci->State = IDLE;
4701       }
4702       break;
4703
4704     case USELAW_REQ:
4705       if(global_req == ASSIGN)
4706       {
4707         if (rc==ASSIGN_OK)
4708       {
4709         sig_req(plci,LAW_REQ,0);
4710         send_req(plci);
4711         dbug(1,dprintf("Auto-Law assigned"));
4712         }
4713         else
4714         {
4715           dbug(1,dprintf("Auto-Law assign failed"));
4716           a->automatic_law = 3;
4717           plci->internal_command = 0;
4718           a->automatic_lawPLCI = NULL;
4719         }
4720         break;
4721       }
4722       else if(req == LAW_REQ && rc==OK)
4723       {
4724         dbug(1,dprintf("Auto-Law initiated"));
4725         a->automatic_law = 2;
4726         plci->internal_command = 0;
4727       }
4728       else
4729       {
4730         dbug(1,dprintf("Auto-Law not supported"));
4731         a->automatic_law = 3;
4732         plci->internal_command = 0;
4733         sig_req(plci,REMOVE,0);
4734         send_req(plci);
4735         a->automatic_lawPLCI = NULL;
4736       }
4737       break;
4738     }
4739     plci_remove_check(plci);
4740   }
4741 }
4742
4743 void data_rc(PLCI   * plci, byte ch)
4744 {
4745   dword Id;
4746   DIVA_CAPI_ADAPTER   * a;
4747   NCCI   *ncci_ptr;
4748   DATA_B3_DESC   *data;
4749   word ncci;
4750
4751   if (plci->appl)
4752   {
4753     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4754     a = plci->adapter;
4755     ncci = a->ch_ncci[ch];
4756     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4757     {
4758       ncci_ptr = &(a->ncci[ncci]);
4759       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4760       if (ncci_ptr->data_pending)
4761       {
4762         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4763         if (!(data->Flags &4) && a->ncci_state[ncci])
4764         {
4765           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4766           if(plci->tel) Id|=EXT_CONTROLLER;
4767           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4768                 "ww",data->Handle,0);
4769         }
4770         (ncci_ptr->data_out)++;
4771         if (ncci_ptr->data_out == MAX_DATA_B3)
4772           ncci_ptr->data_out = 0;
4773         (ncci_ptr->data_pending)--;
4774       }
4775     }
4776   }
4777 }
4778
4779 void data_ack(PLCI   * plci, byte ch)
4780 {
4781   dword Id;
4782   DIVA_CAPI_ADAPTER   * a;
4783   NCCI   *ncci_ptr;
4784   word ncci;
4785
4786   a = plci->adapter;
4787   ncci = a->ch_ncci[ch];
4788   ncci_ptr = &(a->ncci[ncci]);
4789   if (ncci_ptr->data_ack_pending)
4790   {
4791     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4792     {
4793       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4794       if(plci->tel) Id|=EXT_CONTROLLER;
4795       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4796             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4797     }
4798     (ncci_ptr->data_ack_out)++;
4799     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4800       ncci_ptr->data_ack_out = 0;
4801     (ncci_ptr->data_ack_pending)--;
4802   }
4803 }
4804
4805 void sig_ind(PLCI   * plci)
4806 {
4807   dword x_Id;
4808   dword Id;
4809   dword rId;
4810   word Number = 0;
4811   word i;
4812   word cip;
4813   dword cip_mask;
4814   byte   *ie;
4815   DIVA_CAPI_ADAPTER   * a;
4816     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4817 #define MAXPARMSIDS 31
4818     byte   * parms[MAXPARMSIDS];
4819     byte   * add_i[4];
4820     byte   * multi_fac_parms[MAX_MULTI_IE];
4821     byte   * multi_pi_parms [MAX_MULTI_IE];
4822     byte   * multi_ssext_parms [MAX_MULTI_IE];
4823     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4824
4825     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4826
4827   byte ai_len;
4828     byte   *esc_chi = "";
4829     byte   *esc_law = "";
4830     byte   *pty_cai = "";
4831     byte   *esc_cr  = "";
4832     byte   *esc_profile = "";
4833
4834     byte facility[256];
4835   PLCI   * tplci = NULL;
4836   byte chi[] = "\x02\x18\x01";
4837   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4838     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4839   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4840   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4841   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4842   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4843     word parms_id[] =
4844          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4845           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4846           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4847           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4848           /* 14 FTY repl by ESC_CHI */
4849           /* 18 PI  repl by ESC_LAW */
4850          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4851      word multi_fac_id[] = {1, FTY};
4852      word multi_pi_id[]  = {1, PI};
4853      word multi_CiPN_id[]  = {1, OAD};
4854      word multi_ssext_id[]  = {1, ESC_SSEXT};
4855
4856      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4857
4858   byte   * cau;
4859   word ncci;
4860     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4861     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4862     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4863     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4864   byte force_mt_info = false;
4865   byte dir;
4866   dword d;
4867   word w;
4868
4869   a = plci->adapter;
4870   Id = ((word)plci->Id<<8)|a->Id;
4871   PUT_WORD(&SS_Ind[4],0x0000);
4872
4873   if (plci->sig_remove_id)
4874   {
4875     plci->Sig.RNR = 2; /* discard */
4876     dbug(1,dprintf("SIG discard while remove pending"));
4877     return;
4878   }
4879   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4880   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4881     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4882   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4883   {
4884     plci->Sig.RNR = 1;
4885     return;
4886   }
4887   if(plci->Sig.Ind==HANGUP && plci->channels)
4888   {
4889     plci->Sig.RNR = 1;
4890     plci->hangup_flow_ctrl_timer++;
4891     /* recover the network layer after timeout */
4892     if(plci->hangup_flow_ctrl_timer==100)
4893     {
4894       dbug(1,dprintf("Exceptional disc"));
4895       plci->Sig.RNR = 0;
4896       plci->hangup_flow_ctrl_timer = 0;
4897       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4898       {
4899         if (a->ncci_plci[ncci] == plci->Id)
4900         {
4901           cleanup_ncci_data (plci, ncci);
4902           if(plci->channels)plci->channels--;
4903           if (plci->appl)
4904             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4905         }
4906       }
4907       if (plci->appl)
4908         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4909       plci_remove(plci);
4910       plci->State=IDLE;
4911     }
4912     return;
4913   }
4914
4915   /* do first parse the info with no OAD in, because OAD will be converted */
4916   /* first the multiple facility IE, then mult. progress ind.              */
4917   /* then the parameters for the info_ind + conn_ind                       */
4918   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4919   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4920   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4921
4922   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4923
4924   IndParse(plci,parms_id,parms,0);
4925   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4926   esc_chi  = parms[14];
4927   esc_law  = parms[18];
4928   pty_cai  = parms[24];
4929   esc_cr   = parms[25];
4930   esc_profile = parms[27];
4931   if(esc_cr[0] && plci)
4932   {
4933     if(plci->cr_enquiry && plci->appl)
4934     {
4935       plci->cr_enquiry = false;
4936       /* d = MANU_ID            */
4937       /* w = m_command          */
4938       /* b = total length       */
4939       /* b = indication type    */
4940       /* b = length of all IEs  */
4941       /* b = IE1                */
4942       /* S = IE1 length + cont. */
4943       /* b = IE2                */
4944       /* S = IE2 lenght + cont. */
4945       sendf(plci->appl,
4946         _MANUFACTURER_I,
4947         Id,
4948         0,
4949         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4950         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);
4951     }
4952   }
4953   /* create the additional info structure                                  */
4954   add_i[1] = parms[15]; /* KEY of additional info */
4955   add_i[2] = parms[11]; /* UUI of additional info */
4956   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4957
4958   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4959   /* indication returns by the card if requested by the function           */
4960   /* AutomaticLaw() after driver init                                      */
4961   if (a->automatic_law<4)
4962   {
4963     if(esc_law[0]){
4964       if(esc_law[2]){
4965         dbug(0,dprintf("u-Law selected"));
4966         a->u_law = 1;
4967       }
4968       else {
4969         dbug(0,dprintf("a-Law selected"));
4970         a->u_law = 0;
4971       }
4972       a->automatic_law = 4;
4973       if(plci==a->automatic_lawPLCI) {
4974         plci->internal_command = 0;
4975         sig_req(plci,REMOVE,0);
4976         send_req(plci);
4977         a->automatic_lawPLCI = NULL;
4978       }
4979     }
4980     if (esc_profile[0])
4981     {
4982       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4983         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4984         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4985         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4986
4987       a->profile.Global_Options &= 0x000000ffL;
4988       a->profile.B1_Protocols &= 0x000003ffL;
4989       a->profile.B2_Protocols &= 0x00001fdfL;
4990       a->profile.B3_Protocols &= 0x000000b7L;
4991
4992       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4993         GL_BCHANNEL_OPERATION_SUPPORTED;
4994       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4995       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4996       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4997       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4998       a->man_profile.private_options = 0;
4999
5000       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5001       {
5002         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5003         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5004       }
5005
5006
5007       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5008         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5009       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5010       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5011
5012
5013       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5014         a->man_profile.private_options |= 1L << PRIVATE_T38;
5015
5016
5017       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5018         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5019
5020
5021       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5022         a->man_profile.private_options |= 1L << PRIVATE_V18;
5023
5024
5025       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5026         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5027
5028
5029       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5030         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5031
5032
5033       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5034         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5035
5036
5037       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5038         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5039
5040
5041       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5042         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5043
5044     }
5045     else
5046     {
5047       a->profile.Global_Options &= 0x0000007fL;
5048       a->profile.B1_Protocols &= 0x000003dfL;
5049       a->profile.B2_Protocols &= 0x00001adfL;
5050       a->profile.B3_Protocols &= 0x000000b7L;
5051       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5052     }
5053     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5054       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5055     {
5056       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5057     }
5058     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5059     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5060       UnMapController (a->Id), a->profile.Global_Options,
5061       a->profile.B1_Protocols, a->profile.B2_Protocols,
5062       a->profile.B3_Protocols, a->manufacturer_features));
5063   }
5064   /* codec plci for the handset/hook state support is just an internal id  */
5065   if(plci!=a->AdvCodecPLCI)
5066   {
5067     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5068     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5069     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5070     SendInfo(plci,Id, parms, force_mt_info);
5071
5072     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5073
5074   }
5075
5076   /* switch the codec to the b-channel                                     */
5077   if(esc_chi[0] && plci && !plci->SuppState){
5078     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5079     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5080     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5081     if(plci->tel==ADV_VOICE && plci->appl) {
5082       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5083     }
5084   }
5085
5086   if(plci->appl) Number = plci->appl->Number++;
5087
5088   switch(plci->Sig.Ind) {
5089   /* Response to Get_Supported_Services request */
5090   case S_SUPPORTED:
5091     dbug(1,dprintf("S_Supported"));
5092     if(!plci->appl) break;
5093     if(pty_cai[0]==4)
5094     {
5095       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5096     }
5097     else
5098     {
5099       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5100     }
5101     PUT_WORD (&CF_Ind[1], 0);
5102     PUT_WORD (&CF_Ind[4], 0);
5103     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5104     plci_remove(plci);
5105     break;
5106                     
5107   /* Supplementary Service rejected */
5108   case S_SERVICE_REJ:
5109     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5110     if(!pty_cai[0]) break;
5111     switch (pty_cai[5])
5112     {
5113     case ECT_EXECUTE:
5114     case THREE_PTY_END:
5115     case THREE_PTY_BEGIN:
5116       if(!plci->relatedPTYPLCI) break;
5117       tplci = plci->relatedPTYPLCI;
5118       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5119       if(tplci->tel) rId|=EXT_CONTROLLER;
5120       if(pty_cai[5]==ECT_EXECUTE)
5121       {
5122         PUT_WORD(&SS_Ind[1],S_ECT);
5123
5124         plci->vswitchstate=0;
5125         plci->relatedPTYPLCI->vswitchstate=0;
5126
5127       }
5128       else
5129       {
5130         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5131       }
5132       if(pty_cai[2]!=0xff)
5133       {
5134         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5135       }
5136       else
5137       {
5138         PUT_WORD(&SS_Ind[4],0x300E);
5139       }
5140       plci->relatedPTYPLCI = NULL;
5141       plci->ptyState = 0;
5142       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5143       break;
5144
5145     case CALL_DEFLECTION:
5146       if(pty_cai[2]!=0xff)
5147       {
5148         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5149       }
5150       else
5151       {
5152         PUT_WORD(&SS_Ind[4],0x300E);
5153       }
5154       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5155       for(i=0; i<max_appl; i++)
5156       {
5157         if(application[i].CDEnable)
5158         {
5159           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5160           application[i].CDEnable = false;
5161         }
5162       }
5163       break;
5164
5165     case DEACTIVATION_DIVERSION:
5166     case ACTIVATION_DIVERSION:
5167     case DIVERSION_INTERROGATE_CFU:
5168     case DIVERSION_INTERROGATE_CFB:
5169     case DIVERSION_INTERROGATE_CFNR:
5170     case DIVERSION_INTERROGATE_NUM:
5171     case CCBS_REQUEST:
5172     case CCBS_DEACTIVATE:
5173     case CCBS_INTERROGATE:
5174       if(!plci->appl) break;
5175       if(pty_cai[2]!=0xff)
5176       {
5177         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5178       }
5179       else
5180       {
5181         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5182       }
5183       switch (pty_cai[5])
5184       {
5185         case DEACTIVATION_DIVERSION:
5186           dbug(1,dprintf("Deact_Div"));
5187           Interr_Err_Ind[0]=0x9;
5188           Interr_Err_Ind[3]=0x6;
5189           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5190           break;
5191         case ACTIVATION_DIVERSION:
5192           dbug(1,dprintf("Act_Div"));
5193           Interr_Err_Ind[0]=0x9;
5194           Interr_Err_Ind[3]=0x6;
5195           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5196           break;
5197         case DIVERSION_INTERROGATE_CFU:
5198         case DIVERSION_INTERROGATE_CFB:
5199         case DIVERSION_INTERROGATE_CFNR:
5200           dbug(1,dprintf("Interr_Div"));
5201           Interr_Err_Ind[0]=0xa;
5202           Interr_Err_Ind[3]=0x7;
5203           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5204           break;
5205         case DIVERSION_INTERROGATE_NUM:
5206           dbug(1,dprintf("Interr_Num"));
5207           Interr_Err_Ind[0]=0xa;
5208           Interr_Err_Ind[3]=0x7;
5209           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5210           break;
5211         case CCBS_REQUEST:
5212           dbug(1,dprintf("CCBS Request"));
5213           Interr_Err_Ind[0]=0xd;
5214           Interr_Err_Ind[3]=0xa;
5215           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5216           break;
5217         case CCBS_DEACTIVATE:
5218           dbug(1,dprintf("CCBS Deactivate"));
5219           Interr_Err_Ind[0]=0x9;
5220           Interr_Err_Ind[3]=0x6;
5221           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5222           break;
5223         case CCBS_INTERROGATE:
5224           dbug(1,dprintf("CCBS Interrogate"));
5225           Interr_Err_Ind[0]=0xb;
5226           Interr_Err_Ind[3]=0x8;
5227           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5228           break;
5229       }
5230       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5231       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5232       plci_remove(plci);
5233       break;
5234     case ACTIVATION_MWI:      
5235     case DEACTIVATION_MWI:
5236       if(pty_cai[5]==ACTIVATION_MWI)
5237       {
5238         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5239       }
5240       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5241       
5242       if(pty_cai[2]!=0xff)
5243       {
5244         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5245       }
5246       else
5247       {
5248         PUT_WORD(&SS_Ind[4],0x300E);
5249       }
5250
5251       if(plci->cr_enquiry)
5252       {
5253         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5254         plci_remove(plci);
5255       }
5256       else
5257       {
5258         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5259       }
5260       break;
5261     case CONF_ADD: /* ERROR */
5262     case CONF_BEGIN:
5263     case CONF_DROP:
5264     case CONF_ISOLATE:
5265     case CONF_REATTACH:
5266       CONF_Ind[0]=9;
5267       CONF_Ind[3]=6;   
5268       switch(pty_cai[5])
5269       {
5270       case CONF_BEGIN:
5271           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5272           plci->ptyState = 0;
5273           break;
5274       case CONF_DROP:
5275           CONF_Ind[0]=5;
5276           CONF_Ind[3]=2;
5277           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5278           plci->ptyState = CONNECTED;
5279           break;
5280       case CONF_ISOLATE:
5281           CONF_Ind[0]=5;
5282           CONF_Ind[3]=2;
5283           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5284           plci->ptyState = CONNECTED;
5285           break;
5286       case CONF_REATTACH:
5287           CONF_Ind[0]=5;
5288           CONF_Ind[3]=2;
5289           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5290           plci->ptyState = CONNECTED;
5291           break;
5292       case CONF_ADD:
5293           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5294           plci->relatedPTYPLCI = NULL;
5295           tplci=plci->relatedPTYPLCI;
5296           if(tplci) tplci->ptyState = CONNECTED;
5297           plci->ptyState = CONNECTED;
5298           break;
5299       }
5300           
5301       if(pty_cai[2]!=0xff)
5302       {
5303         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5304       }
5305       else
5306       {
5307         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5308                                             within the required time */
5309       }
5310
5311       PUT_DWORD(&CONF_Ind[6],0x0);
5312       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5313       break;
5314     }
5315     break;
5316
5317   /* Supplementary Service indicates success */
5318   case S_SERVICE:
5319     dbug(1,dprintf("Service_Ind"));
5320     PUT_WORD (&CF_Ind[4], 0);
5321     switch (pty_cai[5])
5322     {
5323     case THREE_PTY_END:
5324     case THREE_PTY_BEGIN:
5325     case ECT_EXECUTE:
5326       if(!plci->relatedPTYPLCI) break;
5327       tplci = plci->relatedPTYPLCI;
5328       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5329       if(tplci->tel) rId|=EXT_CONTROLLER;
5330       if(pty_cai[5]==ECT_EXECUTE)
5331       {
5332         PUT_WORD(&SS_Ind[1],S_ECT);
5333
5334         if(plci->vswitchstate!=3)
5335         {
5336
5337         plci->ptyState = IDLE;
5338         plci->relatedPTYPLCI = NULL;
5339         plci->ptyState = 0;
5340
5341         }
5342
5343         dbug(1,dprintf("ECT OK"));
5344         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5345
5346
5347
5348       }
5349       else
5350       {
5351         switch (plci->ptyState)
5352         {
5353         case S_3PTY_BEGIN:
5354           plci->ptyState = CONNECTED;
5355           dbug(1,dprintf("3PTY ON"));
5356           break;
5357
5358         case S_3PTY_END:
5359           plci->ptyState = IDLE;
5360           plci->relatedPTYPLCI = NULL;
5361           plci->ptyState = 0;
5362           dbug(1,dprintf("3PTY OFF"));
5363           break;
5364         }
5365         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5366         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5367       }
5368       break;
5369
5370     case CALL_DEFLECTION:
5371       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5372       for(i=0; i<max_appl; i++)
5373       {
5374         if(application[i].CDEnable)
5375         {
5376           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5377           application[i].CDEnable = false;
5378         }
5379       }
5380       break;
5381
5382     case DEACTIVATION_DIVERSION:
5383     case ACTIVATION_DIVERSION:
5384       if(!plci->appl) break;
5385       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5386       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5387       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5388       plci_remove(plci);
5389       break;
5390
5391     case DIVERSION_INTERROGATE_CFU:
5392     case DIVERSION_INTERROGATE_CFB:
5393     case DIVERSION_INTERROGATE_CFNR:
5394     case DIVERSION_INTERROGATE_NUM:
5395     case CCBS_REQUEST:
5396     case CCBS_DEACTIVATE:
5397     case CCBS_INTERROGATE:
5398       if(!plci->appl) break;
5399       switch (pty_cai[5])
5400       {
5401         case DIVERSION_INTERROGATE_CFU:
5402         case DIVERSION_INTERROGATE_CFB:
5403         case DIVERSION_INTERROGATE_CFNR:
5404           dbug(1,dprintf("Interr_Div"));
5405           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5406           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5407           break;
5408         case DIVERSION_INTERROGATE_NUM:
5409           dbug(1,dprintf("Interr_Num"));
5410           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5411           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5412           break;
5413         case CCBS_REQUEST:
5414           dbug(1,dprintf("CCBS Request"));
5415           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5416           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5417           break;
5418         case CCBS_DEACTIVATE:
5419           dbug(1,dprintf("CCBS Deactivate"));
5420           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5421           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5422           break;
5423         case CCBS_INTERROGATE:
5424           dbug(1,dprintf("CCBS Interrogate"));
5425           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5426           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5427           break;
5428       }
5429       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5430       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5431       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5432       plci_remove(plci);
5433       break;
5434
5435     case ACTIVATION_MWI:
5436     case DEACTIVATION_MWI:
5437       if(pty_cai[5]==ACTIVATION_MWI)
5438       {
5439         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5440       }
5441       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5442       if(plci->cr_enquiry)
5443       {
5444         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5445         plci_remove(plci);
5446       }
5447       else
5448       {
5449         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5450       }
5451       break;
5452     case MWI_INDICATION:
5453       if(pty_cai[0]>=0x12)
5454       {
5455         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5456         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5457         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5458         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5459         {
5460           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5461           {
5462             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5463             plci_remove(plci);
5464             return;
5465           }
5466           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5467           pty_cai[0]=0;
5468         }
5469         else
5470         {
5471           for(i=0; i<max_appl; i++)
5472           {                     
5473             if(a->Notification_Mask[i]&SMASK_MWI)
5474             {
5475               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5476               pty_cai[0]=0;
5477             }
5478           }
5479         }
5480
5481         if(!pty_cai[0])
5482         { /* acknowledge */
5483           facility[2]= 0; /* returncode */
5484         }
5485         else facility[2]= 0xff;
5486       }
5487       else
5488       {
5489         /* reject */
5490         facility[2]= 0xff; /* returncode */
5491       }
5492       facility[0]= 2;
5493       facility[1]= MWI_RESPONSE; /* Function */
5494       add_p(plci,CAI,facility);
5495       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5496       sig_req(plci,S_SERVICE,0);
5497       send_req(plci);
5498       plci->command = 0;
5499       next_internal_command (Id, plci);
5500       break;
5501     case CONF_ADD: /* OK */
5502     case CONF_BEGIN:
5503     case CONF_DROP:
5504     case CONF_ISOLATE:
5505     case CONF_REATTACH:
5506     case CONF_PARTYDISC:
5507       CONF_Ind[0]=9;
5508       CONF_Ind[3]=6;
5509       switch(pty_cai[5])
5510       {
5511       case CONF_BEGIN:
5512           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5513           if(pty_cai[0]==6)
5514           {
5515               d=pty_cai[6];
5516               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5517           }
5518           else
5519           {
5520               PUT_DWORD(&CONF_Ind[6],0x0);
5521           }
5522           break;
5523       case CONF_ISOLATE:
5524           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5525           CONF_Ind[0]=5;
5526           CONF_Ind[3]=2;
5527           break;
5528       case CONF_REATTACH:
5529           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5530           CONF_Ind[0]=5;
5531           CONF_Ind[3]=2;
5532           break;
5533       case CONF_DROP:
5534           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5535           CONF_Ind[0]=5;
5536           CONF_Ind[3]=2;
5537           break;
5538       case CONF_ADD:
5539           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5540           d=pty_cai[6];
5541           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5542           tplci=plci->relatedPTYPLCI;
5543           if(tplci) tplci->ptyState = CONNECTED;
5544           break;
5545       case CONF_PARTYDISC:
5546           CONF_Ind[0]=7;
5547           CONF_Ind[3]=4;          
5548           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5549           d=pty_cai[6];
5550           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5551           break;
5552       }
5553       plci->ptyState = CONNECTED;
5554       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5555       break;
5556     case CCBS_INFO_RETAIN:
5557     case CCBS_ERASECALLLINKAGEID:
5558     case CCBS_STOP_ALERTING:
5559       CONF_Ind[0]=5;
5560       CONF_Ind[3]=2;
5561       switch(pty_cai[5])
5562       {
5563       case CCBS_INFO_RETAIN:
5564         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5565         break;
5566       case CCBS_STOP_ALERTING:
5567         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5568     break;
5569       case CCBS_ERASECALLLINKAGEID:
5570         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5571         CONF_Ind[0]=7;
5572         CONF_Ind[3]=4;
5573         CONF_Ind[6]=0;
5574         CONF_Ind[7]=0;
5575         break;
5576       }      
5577       w=pty_cai[6];
5578       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5579
5580       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5581       {
5582         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5583       }
5584       else
5585       {
5586         for(i=0; i<max_appl; i++)
5587             if(a->Notification_Mask[i]&SMASK_CCBS)
5588                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5589       }
5590       break;
5591     }
5592     break;
5593   case CALL_HOLD_REJ:
5594     cau = parms[7];
5595     if(cau)
5596     {
5597       i = _L3_CAUSE | cau[2];
5598       if(cau[2]==0) i = 0x3603;
5599     }
5600     else
5601     {
5602       i = 0x3603;
5603     }
5604     PUT_WORD(&SS_Ind[1],S_HOLD);
5605     PUT_WORD(&SS_Ind[4],i);
5606     if(plci->SuppState == HOLD_REQUEST)
5607     {
5608       plci->SuppState = IDLE;
5609       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5610     }
5611     break;
5612
5613   case CALL_HOLD_ACK:
5614     if(plci->SuppState == HOLD_REQUEST)
5615     {
5616       plci->SuppState = CALL_HELD;
5617       CodecIdCheck(a, plci);
5618       start_internal_command (Id, plci, hold_save_command);
5619     }
5620     break;
5621
5622   case CALL_RETRIEVE_REJ:
5623     cau = parms[7];
5624     if(cau)
5625     {
5626       i = _L3_CAUSE | cau[2];
5627       if(cau[2]==0) i = 0x3603;
5628     }
5629     else
5630     {
5631       i = 0x3603;
5632     }
5633     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5634     PUT_WORD(&SS_Ind[4],i);
5635     if(plci->SuppState == RETRIEVE_REQUEST)
5636     {
5637       plci->SuppState = CALL_HELD;
5638       CodecIdCheck(a, plci);
5639       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5640     }
5641     break;
5642
5643   case CALL_RETRIEVE_ACK:
5644     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5645     if(plci->SuppState == RETRIEVE_REQUEST)
5646     {
5647       plci->SuppState = IDLE;
5648       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5649       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5650       if(plci->tel)
5651       {
5652         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5653         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5654         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5655         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5656         {
5657           dbug(1,dprintf("Get B-ch"));
5658           start_internal_command (Id, plci, retrieve_restore_command);
5659         }
5660         else
5661           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5662       }
5663       else
5664         start_internal_command (Id, plci, retrieve_restore_command);
5665     }
5666     break;
5667
5668   case INDICATE_IND:
5669     if(plci->State != LISTENING) {
5670       sig_req(plci,HANGUP,0);
5671       send_req(plci);
5672       break;
5673     }
5674     cip = find_cip(a,parms[4],parms[6]);
5675     cip_mask = 1L<<cip;
5676     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5677     clear_c_ind_mask (plci);
5678     if (!remove_started && !a->adapter_disabled)
5679     {
5680       set_c_ind_mask_bit (plci, MAX_APPL);
5681       group_optimization(a, plci);
5682       for(i=0; i<max_appl; i++) {
5683         if(application[i].Id
5684         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5685         && CPN_filter_ok(parms[0],a,i)
5686         && test_group_ind_mask_bit (plci, i) ) {
5687           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5688           set_c_ind_mask_bit (plci, i);
5689           dump_c_ind_mask (plci);
5690           plci->State = INC_CON_PENDING;
5691           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5692             CALL_DIR_IN | CALL_DIR_ANSWER;
5693           if(esc_chi[0]) {
5694             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5695             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5696           }
5697           /* if a listen on the ext controller is done, check if hook states */
5698           /* are supported or if just a on board codec must be activated     */
5699           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5700             if(a->profile.Global_Options & HANDSET)
5701               plci->tel = ADV_VOICE;
5702             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5703               plci->tel = CODEC;
5704             if(plci->tel) Id|=EXT_CONTROLLER;
5705             a->codec_listen[i] = plci;
5706           }
5707
5708           sendf(&application[i],_CONNECT_I,Id,0,
5709                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5710                              parms[0],    /* CalledPartyNumber   */
5711                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5712                              parms[2],    /* CalledPartySubad    */
5713                              parms[3],    /* CallingPartySubad   */
5714                              parms[4],    /* BearerCapability    */
5715                              parms[5],    /* LowLC               */
5716                              parms[6],    /* HighLC              */
5717                              ai_len,      /* nested struct add_i */
5718                              add_i[0],    /* B channel info    */
5719                              add_i[1],    /* keypad facility   */
5720                              add_i[2],    /* user user data    */
5721                              add_i[3],    /* nested facility   */
5722                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5723                              );
5724           SendSSExtInd(&application[i],
5725                         plci,
5726                         Id,
5727                         multi_ssext_parms);
5728           SendSetupInfo(&application[i],
5729                         plci,
5730                         Id,
5731                         parms,
5732                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5733         }
5734       }
5735       clear_c_ind_mask_bit (plci, MAX_APPL);
5736       dump_c_ind_mask (plci);
5737     }
5738     if(c_ind_mask_empty (plci)) {
5739       sig_req(plci,HANGUP,0);
5740       send_req(plci);
5741       plci->State = IDLE;
5742     }
5743     plci->notifiedcall = 0;
5744     a->listen_active--;
5745     listen_check(a);
5746     break;
5747
5748   case CALL_PEND_NOTIFY:
5749     plci->notifiedcall = 1;
5750     listen_check(a);
5751     break;
5752
5753   case CALL_IND:
5754   case CALL_CON:
5755     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5756     {
5757       if(plci->internal_command==PERM_COD_CONN_PEND)
5758       {
5759         if(plci->State==ADVANCED_VOICE_NOSIG)
5760         {
5761           dbug(1,dprintf("***Codec OK"));
5762           if(a->AdvSignalPLCI)
5763           {
5764             tplci = a->AdvSignalPLCI;
5765             if(tplci->spoofed_msg)
5766             {
5767               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5768               tplci->command = 0;
5769               tplci->internal_command = 0;
5770               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5771               switch (tplci->spoofed_msg)
5772               {
5773               case CALL_RES:
5774                 tplci->command = _CONNECT_I|RESPONSE;
5775                 api_load_msg (&tplci->saved_msg, saved_parms);
5776                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5777                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5778                 {
5779                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5780                   add_p(tplci,LLI,"\x01\x01");
5781                 }
5782                 add_s(tplci, CONN_NR, &saved_parms[2]);
5783                 add_s(tplci, LLC, &saved_parms[4]);
5784                 add_ai(tplci, &saved_parms[5]);
5785                 tplci->State = INC_CON_ACCEPT;
5786                 sig_req(tplci, CALL_RES,0);
5787                 send_req(tplci);
5788                 break;
5789
5790               case AWAITING_SELECT_B:
5791                 dbug(1,dprintf("Select_B continue"));
5792                 start_internal_command (x_Id, tplci, select_b_command);
5793                 break;
5794
5795               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5796                 if(!tplci->Sig.Id)
5797                 {
5798                   dbug(1,dprintf("No SigID!"));
5799                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5800                   plci_remove(tplci);
5801                   break;
5802                 }
5803                 tplci->command = _MANUFACTURER_R;
5804                 api_load_msg (&tplci->saved_msg, saved_parms);
5805                 dir = saved_parms[2].info[0];
5806                 if(dir==1) {
5807                   sig_req(tplci,CALL_REQ,0);
5808                 }
5809                 else if(!dir){
5810                   sig_req(tplci,LISTEN_REQ,0);
5811                 }
5812                 send_req(tplci);
5813                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5814                 break;
5815
5816               case (CALL_REQ|AWAITING_MANUF_CON):
5817                 sig_req(tplci,CALL_REQ,0);
5818                 send_req(tplci);
5819                 break;
5820
5821               case CALL_REQ:
5822                 if(!tplci->Sig.Id)
5823                 {
5824                   dbug(1,dprintf("No SigID!"));
5825                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5826                   plci_remove(tplci);
5827                   break;
5828                 }
5829                 tplci->command = _CONNECT_R;
5830                 api_load_msg (&tplci->saved_msg, saved_parms);
5831                 add_s(tplci,CPN,&saved_parms[1]);
5832                 add_s(tplci,DSA,&saved_parms[3]);
5833                 add_ai(tplci,&saved_parms[9]);
5834                 sig_req(tplci,CALL_REQ,0);
5835                 send_req(tplci);
5836                 break;
5837
5838               case CALL_RETRIEVE:
5839                 tplci->command = C_RETRIEVE_REQ;
5840                 sig_req(tplci,CALL_RETRIEVE,0);
5841                 send_req(tplci);
5842                 break;
5843               }
5844               tplci->spoofed_msg = 0;
5845               if (tplci->internal_command == 0)
5846                 next_internal_command (x_Id, tplci);
5847             }
5848           }
5849           next_internal_command (Id, plci);
5850           break;
5851         }
5852         dbug(1,dprintf("***Codec Hook Init Req"));
5853         plci->internal_command = PERM_COD_HOOK;
5854         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5855         sig_req(plci,TEL_CTRL,0);
5856         send_req(plci);
5857       }
5858     }
5859     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5860     && plci->State!=INC_ACT_PENDING)
5861     {
5862       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5863       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5864       {
5865         chi[2] = plci->b_channel;
5866         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5867       }
5868       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5869       plci->State = INC_ACT_PENDING;
5870     }
5871     break;
5872
5873   case TEL_CTRL:
5874     Number = 0;
5875     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5876     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5877       switch (ie[1]&0x91) {
5878         case 0x80:   /* hook off */
5879         case 0x81:
5880           if(plci->internal_command==PERM_COD_HOOK)
5881           {
5882             dbug(1,dprintf("init:hook_off"));
5883             plci->hook_state = ie[1];
5884             next_internal_command (Id, plci);
5885             break;
5886           }
5887           else /* ignore doubled hook indications */
5888           {
5889             if( ((plci->hook_state)&0xf0)==0x80)
5890             {
5891               dbug(1,dprintf("ignore hook"));
5892               break;
5893             }
5894             plci->hook_state = ie[1]&0x91;
5895           }
5896           /* check for incoming call pending */
5897           /* and signal '+'.Appl must decide */
5898           /* with connect_res if call must   */
5899           /* accepted or not                 */
5900           for(i=0, tplci=NULL;i<max_appl;i++){
5901             if(a->codec_listen[i]
5902             && (a->codec_listen[i]->State==INC_CON_PENDING
5903               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5904               tplci = a->codec_listen[i];
5905               tplci->appl = &application[i];
5906             }
5907           }
5908           /* no incoming call, do outgoing call */
5909           /* and signal '+' if outg. setup   */
5910           if(!a->AdvSignalPLCI && !tplci){
5911             if((i=get_plci(a))) {
5912               a->AdvSignalPLCI = &a->plci[i-1];
5913               tplci = a->AdvSignalPLCI;
5914               tplci->tel  = ADV_VOICE;
5915               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5916               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5917                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5918                 add_p(tplci,LLI,"\x01\x01");
5919               }
5920               add_p(tplci, CAI, voice_cai);
5921               add_p(tplci, OAD, a->TelOAD);
5922               add_p(tplci, OSA, a->TelOSA);
5923               add_p(tplci,SHIFT|6,NULL);
5924               add_p(tplci,SIN,"\x02\x01\x00");
5925               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5926               sig_req(tplci,ASSIGN,DSIG_ID);
5927               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5928               a->AdvSignalPLCI->command = 0;
5929               tplci->appl = a->AdvSignalAppl;
5930               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5931               send_req(tplci);
5932             }
5933
5934           }
5935
5936           if(!tplci) break;
5937           Id = ((word)tplci->Id<<8)|a->Id;
5938           Id|=EXT_CONTROLLER;
5939           sendf(tplci->appl,
5940                 _FACILITY_I,
5941                 Id,
5942                 0,
5943                 "ws", (word)0, "\x01+");
5944           break;
5945
5946         case 0x90:   /* hook on  */
5947         case 0x91:
5948           if(plci->internal_command==PERM_COD_HOOK)
5949           {
5950             dbug(1,dprintf("init:hook_on"));
5951             plci->hook_state = ie[1]&0x91;
5952             next_internal_command (Id, plci);
5953             break;
5954           }
5955           else /* ignore doubled hook indications */
5956           {
5957             if( ((plci->hook_state)&0xf0)==0x90) break;
5958             plci->hook_state = ie[1]&0x91;
5959           }
5960           /* hangup the adv. voice call and signal '-' to the appl */
5961           if(a->AdvSignalPLCI) {
5962             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5963             if(plci->tel) Id|=EXT_CONTROLLER;
5964             sendf(a->AdvSignalAppl,
5965                   _FACILITY_I,
5966                   Id,
5967                   0,
5968                   "ws", (word)0, "\x01-");
5969             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5970             a->AdvSignalPLCI->command = 0;
5971             sig_req(a->AdvSignalPLCI,HANGUP,0);
5972             send_req(a->AdvSignalPLCI);
5973           }
5974           break;
5975       }
5976     }
5977     break;
5978
5979   case RESUME:
5980     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5981     PUT_WORD(&resume_cau[4],GOOD);
5982     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5983     break;
5984
5985   case SUSPEND:
5986     clear_c_ind_mask (plci);
5987
5988     if (plci->NL.Id && !plci->nl_remove_id) {
5989       mixer_remove (plci);
5990       nl_req_ncci(plci,REMOVE,0);
5991     }
5992     if (!plci->sig_remove_id) {
5993       plci->internal_command = 0;
5994       sig_req(plci,REMOVE,0);
5995     }
5996     send_req(plci);
5997     if(!plci->channels) {
5998       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5999       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6000     }
6001     break;
6002
6003   case SUSPEND_REJ:
6004     break;
6005
6006   case HANGUP:
6007     plci->hangup_flow_ctrl_timer=0;
6008     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6009     cau = parms[7];
6010     if(cau) {
6011       i = _L3_CAUSE | cau[2];
6012       if(cau[2]==0) i = 0;
6013       else if(cau[2]==8) i = _L1_ERROR;
6014       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6015       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6016     }
6017     else {
6018       i = _L3_ERROR;
6019     }
6020
6021     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6022     {
6023       for(i=0; i<max_appl; i++)
6024       {
6025         if(test_c_ind_mask_bit (plci, i))
6026           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6027       }
6028     }
6029     else
6030     {
6031       clear_c_ind_mask (plci);
6032     }
6033     if(!plci->appl)
6034     {
6035       if (plci->State == LISTENING)
6036       {
6037         plci->notifiedcall=0;
6038         a->listen_active--;
6039       }
6040       plci->State = INC_DIS_PENDING;
6041       if(c_ind_mask_empty (plci))
6042       {
6043         plci->State = IDLE;
6044         if (plci->NL.Id && !plci->nl_remove_id)
6045         {
6046           mixer_remove (plci);
6047           nl_req_ncci(plci,REMOVE,0);
6048         }
6049         if (!plci->sig_remove_id)
6050         {
6051           plci->internal_command = 0;
6052           sig_req(plci,REMOVE,0);
6053         }
6054         send_req(plci);
6055       }
6056     }
6057     else
6058     {
6059         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6060         /* result in a second HANGUP! Don't generate another        */
6061         /* DISCONNECT                                               */
6062       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6063       {
6064         if(plci->State==RESUMING)
6065         {
6066           PUT_WORD(&resume_cau[4],i);
6067           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6068         }
6069         plci->State = INC_DIS_PENDING;
6070         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6071       }
6072     }
6073     break;
6074
6075   case SSEXT_IND:
6076     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6077     break;
6078
6079   case VSWITCH_REQ:
6080     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6081     break;
6082   case VSWITCH_IND:
6083  if(plci->relatedPTYPLCI &&
6084   plci->vswitchstate==3 &&
6085   plci->relatedPTYPLCI->vswitchstate==3 &&
6086   parms[MAXPARMSIDS-1][0])
6087  {
6088   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6089   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6090   send_req(plci->relatedPTYPLCI);
6091  }
6092     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6093     break;
6094
6095   }
6096 }
6097
6098
6099 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6100 {
6101   word i;
6102   byte   * ie;
6103   word Info_Number;
6104   byte   * Info_Element;
6105   word Info_Mask = 0;
6106
6107   dbug(1,dprintf("SetupInfo"));
6108
6109   for(i=0; i<MAXPARMSIDS; i++) {
6110     ie = parms[i];
6111     Info_Number = 0;
6112     Info_Element = ie;
6113     if(ie[0]) {
6114       switch(i) {
6115       case 0:
6116         dbug(1,dprintf("CPN "));
6117         Info_Number = 0x0070;
6118         Info_Mask   = 0x80;
6119         Info_Sent_Flag = true;
6120         break;
6121       case 8:  /* display      */
6122         dbug(1,dprintf("display(%d)",i));
6123         Info_Number = 0x0028;
6124         Info_Mask = 0x04;
6125         Info_Sent_Flag = true;
6126         break;
6127       case 16: /* Channel Id */
6128         dbug(1,dprintf("CHI"));
6129         Info_Number = 0x0018;
6130         Info_Mask = 0x100;
6131         Info_Sent_Flag = true;
6132         mixer_set_bchannel_id (plci, Info_Element);
6133         break;
6134       case 19: /* Redirected Number */
6135         dbug(1,dprintf("RDN"));
6136         Info_Number = 0x0074;
6137         Info_Mask = 0x400;
6138         Info_Sent_Flag = true;
6139         break;
6140       case 20: /* Redirected Number extended */
6141         dbug(1,dprintf("RDX"));
6142         Info_Number = 0x0073;
6143         Info_Mask = 0x400;
6144         Info_Sent_Flag = true;
6145         break;
6146       case 22: /* Redirecing Number  */
6147         dbug(1,dprintf("RIN"));
6148         Info_Number = 0x0076;
6149         Info_Mask = 0x400;
6150         Info_Sent_Flag = true;
6151         break;
6152       default:
6153         Info_Number = 0;
6154         break;
6155       }
6156     }
6157
6158     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6159       Info_Number = 0x8000 |5;
6160       Info_Mask = 0x10;
6161       Info_Element = "";
6162     }
6163
6164     if(Info_Sent_Flag && Info_Number){
6165       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6166         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6167       }
6168     }
6169   }
6170 }
6171
6172
6173 void SendInfo(PLCI   * plci, dword Id, byte   * * parms, byte iesent)
6174 {
6175   word i;
6176   word j;
6177   word k;
6178   byte   * ie;
6179   word Info_Number;
6180   byte   * Info_Element;
6181   word Info_Mask = 0;
6182   static byte charges[5] = {4,0,0,0,0};
6183   static byte cause[] = {0x02,0x80,0x00};
6184   APPL   *appl;
6185
6186   dbug(1,dprintf("InfoParse "));
6187
6188   if(
6189         !plci->appl
6190         && !plci->State
6191         && plci->Sig.Ind!=NCR_FACILITY
6192       )
6193   {
6194     dbug(1,dprintf("NoParse "));
6195     return;
6196   }
6197   cause[2] = 0;
6198   for(i=0; i<MAXPARMSIDS; i++) {
6199     ie = parms[i];
6200     Info_Number = 0;
6201     Info_Element = ie;
6202     if(ie[0]) {
6203       switch(i) {
6204       case 0:
6205         dbug(1,dprintf("CPN "));
6206         Info_Number = 0x0070;
6207         Info_Mask   = 0x80;
6208         break;
6209       case 7: /* ESC_CAU */
6210         dbug(1,dprintf("cau(0x%x)",ie[2]));
6211         Info_Number = 0x0008;
6212         Info_Mask = 0x00;
6213         cause[2] = ie[2];
6214         Info_Element = NULL;
6215         break;
6216       case 8:  /* display      */
6217         dbug(1,dprintf("display(%d)",i));
6218         Info_Number = 0x0028;
6219         Info_Mask = 0x04;
6220         break;
6221       case 9:  /* Date display */
6222         dbug(1,dprintf("date(%d)",i));
6223         Info_Number = 0x0029;
6224         Info_Mask = 0x02;
6225         break;
6226       case 10: /* charges */
6227         for(j=0;j<4;j++) charges[1+j] = 0;
6228         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6229         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6230         Info_Number = 0x4000;
6231         Info_Mask = 0x40;
6232         Info_Element = charges;
6233         break;
6234       case 11: /* user user info */
6235         dbug(1,dprintf("uui"));
6236         Info_Number = 0x007E;
6237         Info_Mask = 0x08;
6238         break;
6239       case 12: /* congestion receiver ready */
6240         dbug(1,dprintf("clRDY"));
6241         Info_Number = 0x00B0;
6242         Info_Mask = 0x08;
6243         Info_Element = "";
6244         break;
6245       case 13: /* congestion receiver not ready */
6246         dbug(1,dprintf("clNRDY"));
6247         Info_Number = 0x00BF;
6248         Info_Mask = 0x08;
6249         Info_Element = "";
6250         break;
6251       case 15: /* Keypad Facility */
6252         dbug(1,dprintf("KEY"));
6253         Info_Number = 0x002C;
6254         Info_Mask = 0x20;
6255         break;
6256       case 16: /* Channel Id */
6257         dbug(1,dprintf("CHI"));
6258         Info_Number = 0x0018;
6259         Info_Mask = 0x100;
6260         mixer_set_bchannel_id (plci, Info_Element);
6261         break;
6262       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6263         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6264         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6265         Info_Number = 0x0008;
6266         Info_Mask = 0x01;
6267         if(cause[2] != ie[2]) Info_Element = cause;
6268         break;
6269       case 19: /* Redirected Number */
6270         dbug(1,dprintf("RDN"));
6271         Info_Number = 0x0074;
6272         Info_Mask = 0x400;
6273         break;
6274       case 22: /* Redirecing Number  */
6275         dbug(1,dprintf("RIN"));
6276         Info_Number = 0x0076;
6277         Info_Mask = 0x400;
6278         break;
6279       case 23: /* Notification Indicator  */
6280         dbug(1,dprintf("NI"));
6281         Info_Number = (word)NI;
6282         Info_Mask = 0x210;
6283         break;
6284       case 26: /* Call State  */
6285         dbug(1,dprintf("CST"));
6286         Info_Number = (word)CST;
6287         Info_Mask = 0x01; /* do with cause i.e. for now */
6288         break;
6289       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6290         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6291         Info_Number = 0x8000 |ie[3];
6292         if(iesent) Info_Mask = 0xffff;
6293         else  Info_Mask = 0x10;
6294         Info_Element = "";
6295         break;
6296       default:
6297         Info_Number  = 0;
6298         Info_Mask    = 0;
6299         Info_Element = "";
6300         break;
6301       }
6302     }
6303
6304     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6305     {
6306       for(j=0; j<max_appl; j++)
6307       {
6308         appl = &application[j];
6309         if(Info_Number
6310         && appl->Id
6311         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6312         {
6313           dbug(1,dprintf("NCR_Ind"));
6314           iesent=true;
6315           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6316         }
6317       }
6318     }
6319     else if(!plci->appl)
6320     { /* overlap receiving broadcast */
6321       if(Info_Number==CPN
6322       || Info_Number==KEY
6323       || Info_Number==NI
6324       || Info_Number==DSP
6325       || Info_Number==UUI )
6326       {
6327         for(j=0; j<max_appl; j++)
6328         {
6329           if(test_c_ind_mask_bit (plci, j))
6330           {
6331             dbug(1,dprintf("Ovl_Ind"));
6332             iesent=true;
6333             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6334           }
6335         }
6336       }
6337     }               /* all other signalling states */
6338     else if(Info_Number
6339     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6340     {
6341       dbug(1,dprintf("Std_Ind"));
6342       iesent=true;
6343       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6344     }
6345   }
6346 }
6347
6348
6349 byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse)
6350 {
6351   word i;
6352   word j;
6353   byte   * ie;
6354   word Info_Number;
6355   byte   * Info_Element;
6356   APPL   *appl;
6357   word Info_Mask = 0;
6358   byte iesent=0;
6359
6360   if(
6361       !plci->appl
6362       && !plci->State
6363       && plci->Sig.Ind!=NCR_FACILITY
6364       && !setupParse
6365       )
6366   {
6367     dbug(1,dprintf("NoM-IEParse "));
6368     return 0;
6369   }
6370   dbug(1,dprintf("M-IEParse "));
6371
6372   for(i=0; i<MAX_MULTI_IE; i++)
6373   {
6374     ie = parms[i];
6375     Info_Number = 0;
6376     Info_Element = ie;
6377     if(ie[0])
6378     {
6379       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6380       Info_Number = (word)ie_type;
6381       Info_Mask = (word)info_mask;
6382     }
6383
6384     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6385     {
6386       for(j=0; j<max_appl; j++)
6387       {
6388         appl = &application[j];
6389         if(Info_Number
6390         && appl->Id
6391         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6392         {
6393           iesent = true;
6394           dbug(1,dprintf("Mlt_NCR_Ind"));
6395           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6396         }
6397       }
6398     }
6399     else if(!plci->appl && Info_Number)
6400     {                                        /* overlap receiving broadcast */
6401       for(j=0; j<max_appl; j++)
6402       {
6403         if(test_c_ind_mask_bit (plci, j))
6404         {
6405           iesent = true;
6406           dbug(1,dprintf("Mlt_Ovl_Ind"));
6407           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6408         }
6409       }
6410     }                                        /* all other signalling states */
6411     else if(Info_Number
6412     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6413     {
6414       iesent = true;
6415       dbug(1,dprintf("Mlt_Std_Ind"));
6416       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6417     }
6418   }
6419   return iesent;
6420 }
6421
6422 static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6423 {
6424   word i;
6425    /* Format of multi_ssext_parms[i][]:
6426    0 byte length
6427    1 byte SSEXTIE
6428    2 byte SSEXT_REQ/SSEXT_IND
6429    3 byte length
6430    4 word SSExtCommand
6431    6... Params
6432    */
6433   if(
6434    plci
6435    && plci->State
6436    && plci->Sig.Ind!=NCR_FACILITY
6437     )
6438  for(i=0;i<MAX_MULTI_IE;i++)
6439     {
6440       if(parms[i][0]<6) continue;
6441    if(parms[i][2]==SSEXT_REQ) continue;
6442
6443    if(appl)
6444    {
6445     parms[i][0]=0; /* kill it */
6446     sendf(appl,_MANUFACTURER_I,
6447     Id,
6448     0,
6449     "dwS",
6450     _DI_MANU_ID,
6451     _DI_SSEXT_CTRL,
6452     &parms[i][3]);
6453    }
6454    else if(plci->appl)
6455    {
6456     parms[i][0]=0; /* kill it */
6457     sendf(plci->appl,_MANUFACTURER_I,
6458     Id,
6459     0,
6460     "dwS",
6461     _DI_MANU_ID,
6462     _DI_SSEXT_CTRL,
6463     &parms[i][3]);
6464    }
6465     }
6466 };
6467
6468 void nl_ind(PLCI   * plci)
6469 {
6470   byte ch;
6471   word ncci;
6472   dword Id;
6473   DIVA_CAPI_ADAPTER   * a;
6474   word NCCIcode;
6475   APPL   * APPLptr;
6476   word count;
6477   word Num;
6478   word i, ncpi_state;
6479   byte len, ncci_state;
6480   word msg;
6481   word info = 0;
6482   word fax_feature_bits;
6483   byte fax_send_edata_ack;
6484   static byte v120_header_buffer[2 + 3];
6485   static word fax_info[] = {
6486     0,                     /* T30_SUCCESS                        */
6487     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6488     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6489     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6490     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6491     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6492     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6493     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6494     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6495     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6496     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6497     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6498     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6499     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6500     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6501     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6502     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6503     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6504     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6505     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6506     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6507     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6508     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6509     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6510     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6511     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6512     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6513     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6514     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6516     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6517     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6518     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6519     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6520     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6521     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6522     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6523     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6524     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6525     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6526     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6527     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6528     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6529     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6530     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6531     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6532     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6533   };
6534
6535     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6536
6537
6538   static word rtp_info[] = {
6539     GOOD,                  /* RTP_SUCCESS                       */
6540     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6541   };
6542
6543   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6544   {
6545     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6546     0x00000000, 0x00000000, 0x00000000, 0x00000000
6547   };
6548
6549   ch = plci->NL.IndCh;
6550   a = plci->adapter;
6551   ncci = a->ch_ncci[ch];
6552   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6553   if(plci->tel) Id|=EXT_CONTROLLER;
6554   APPLptr = plci->appl;
6555   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",
6556     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6557
6558   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6559
6560   if (plci->nl_remove_id)
6561   {
6562     plci->NL.RNR = 2; /* discard */
6563     dbug(1,dprintf("NL discard while remove pending"));
6564     return;
6565   }
6566   if((plci->NL.Ind &0x0f)==N_CONNECT)
6567   {
6568     if(plci->State==INC_DIS_PENDING
6569     || plci->State==OUTG_DIS_PENDING
6570     || plci->State==IDLE)
6571     {
6572       plci->NL.RNR = 2; /* discard */
6573       dbug(1,dprintf("discard n_connect"));
6574       return;
6575     }
6576     if(plci->State < INC_ACT_PENDING)
6577     {
6578       plci->NL.RNR = 1; /* flow control */
6579       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6580       return;
6581     }
6582   }
6583
6584   if(!APPLptr)                         /* no application or invalid data */
6585   {                                    /* while reloading the DSP        */
6586     dbug(1,dprintf("discard1"));
6587     plci->NL.RNR = 2;
6588     return;
6589   }
6590
6591   if (((plci->NL.Ind &0x0f) == N_UDATA)
6592      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6593         || (plci->B2_prot == 7)
6594         || (plci->B3_prot == 7)) )
6595   {
6596     plci->ncpi_buffer[0] = 0;
6597
6598     ncpi_state = plci->ncpi_state;
6599     if (plci->NL.complete == 1)
6600     {
6601       byte  * data = &plci->NL.RBuffer->P[0];
6602
6603       if ((plci->NL.RBuffer->length >= 12)
6604         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6605           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6606       {
6607         word conn_opt, ncpi_opt = 0x00;
6608 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6609
6610         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6611           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6612         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6613           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6614
6615         data++;    /* indication code */
6616         data += 2; /* timestamp */
6617         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6618           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6619         data++;    /* connected norm */
6620         conn_opt = GET_WORD(data);
6621         data += 2; /* connected options */
6622
6623         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6624
6625         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6626         {
6627           ncpi_opt |= MDM_NCPI_ECM_V42;
6628         }
6629         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6630         {
6631           ncpi_opt |= MDM_NCPI_ECM_MNP;
6632         }
6633         else
6634         {
6635           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6636         }
6637         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6638         {
6639           ncpi_opt |= MDM_NCPI_COMPRESSED;
6640         }
6641         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6642         plci->ncpi_buffer[0] = 4;
6643
6644         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6645       }
6646     }
6647     if (plci->B3_prot == 7)
6648     {
6649       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6650        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6651        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6652       {
6653         a->ncci_state[ncci] = INC_ACT_PENDING;
6654         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6655         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6656       }
6657     }
6658
6659     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6660         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6661      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6662      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6663
6664     {
6665       plci->NL.RNR = 2;
6666       return;
6667     }
6668   }
6669
6670   if(plci->NL.complete == 2)
6671     {
6672     if (((plci->NL.Ind &0x0f) == N_UDATA)
6673      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6674     {
6675       switch(plci->RData[0].P[0])
6676       {
6677
6678       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6679         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6680           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6681         break;
6682       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6683         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6684           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6685         break;
6686       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6687         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6688         break;
6689       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6690         dtmf_confirmation (Id, plci);
6691         break;
6692
6693
6694       case UDATA_INDICATION_MIXER_TAP_DATA:
6695         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6696  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6697  if (i != 0)
6698  {
6699    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6700           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6701  }
6702         break;
6703
6704
6705       case UDATA_INDICATION_MIXER_COEFS_SET:
6706         mixer_indication_coefs_set (Id, plci);
6707         break;
6708       case UDATA_INDICATION_XCONNECT_FROM:
6709         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6710         break;
6711       case UDATA_INDICATION_XCONNECT_TO:
6712         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6713         break;
6714
6715
6716       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6717         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6718         break;
6719
6720
6721
6722       default:
6723         break;
6724       }
6725     }
6726     else
6727   {
6728       if ((plci->RData[0].PLength != 0)
6729      && ((plci->B2_prot == B2_V120_ASYNC)
6730       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6731       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6732     {
6733
6734       sendf(plci->appl,_DATA_B3_I,Id,0,
6735             "dwww",
6736             plci->RData[1].P,
6737               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6738             plci->RNum,
6739             plci->RFlags);
6740
6741     }
6742     else
6743     {
6744
6745       sendf(plci->appl,_DATA_B3_I,Id,0,
6746             "dwww",
6747             plci->RData[0].P,
6748             plci->RData[0].PLength,
6749             plci->RNum,
6750             plci->RFlags);
6751
6752     }
6753     }
6754     return;
6755   }
6756
6757   fax_feature_bits = 0;
6758   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6759      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6760      (plci->NL.Ind &0x0f)==N_DISC ||
6761      (plci->NL.Ind &0x0f)==N_EDATA ||
6762      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6763   {
6764     info = 0;
6765     plci->ncpi_buffer[0] = 0;
6766     switch (plci->B3_prot) {
6767     case  0: /*XPARENT*/
6768     case  1: /*T.90 NL*/
6769       break;    /* no network control protocol info - jfr */
6770     case  2: /*ISO8202*/
6771     case  3: /*X25 DCE*/
6772       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6773       plci->ncpi_buffer[0] = (byte)(i+3);
6774       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6775       plci->ncpi_buffer[2] = 0;
6776       plci->ncpi_buffer[3] = 0;
6777       break;
6778     case  4: /*T.30 - FAX*/
6779     case  5: /*T.30 - FAX*/
6780       if(plci->NL.RLength>=sizeof(T30_INFO))
6781       {
6782         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6783         len = 9;
6784         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6785         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6786         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6787         if (plci->B3_prot == 5)
6788         {
6789           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6790             i |= 0x8000; /* This is not an ECM connection */
6791           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6792             i |= 0x4000; /* This is a connection with MMR compression */
6793           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6794             i |= 0x2000; /* This is a connection with MR compression */
6795           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6796             i |= 0x0004; /* More documents */
6797           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6798             i |= 0x0002; /* Fax-polling indication */
6799         }
6800         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6801         PUT_WORD(&(plci->ncpi_buffer[3]),i);
6802         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6803         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6804         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6805         plci->ncpi_buffer[len] = 0;
6806         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6807         {
6808           plci->ncpi_buffer[len] = 20;
6809           for (i = 0; i < 20; i++)
6810             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6811         }
6812         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6813         {
6814           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6815             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6816           else
6817             info = _FAX_PROTOCOL_ERROR;
6818         }
6819
6820         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6821           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6822         {
6823           i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6824           while (i < plci->NL.RBuffer->length)
6825             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6826         }
6827
6828         plci->ncpi_buffer[0] = len;
6829         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6830         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6831
6832         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6833  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6834          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6835           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6836          || (((plci->NL.Ind &0x0f) == N_EDATA)
6837           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6838            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6839            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6840  {
6841           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6842  }
6843  if (((plci->NL.Ind &0x0f) == N_DISC)
6844   || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6845   || (((plci->NL.Ind &0x0f) == N_EDATA)
6846    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6847  {
6848           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6849  }
6850       }
6851       break;
6852
6853     case B3_RTP:
6854       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6855       {
6856         if (plci->NL.RLength != 0)
6857         {
6858           info = rtp_info[plci->NL.RBuffer->P[0]];
6859           plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6860           for (i = 1; i < plci->NL.RLength; i++)
6861             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6862         }
6863       }
6864       break;
6865
6866     }
6867     plci->NL.RNR = 2;
6868   }
6869   switch(plci->NL.Ind &0x0f) {
6870   case N_EDATA:
6871     if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6872     {
6873       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6874         ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6875       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6876
6877       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6878        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6879        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6880        && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6881        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6882        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6883       {
6884         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6885         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6886           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6887         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6888  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6889    fax_send_edata_ack = false;
6890       }
6891
6892       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6893       {
6894         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6895         {
6896         case EDATA_T30_DIS:
6897           if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6898            && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6899            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6900            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6901           {
6902             a->ncci_state[ncci] = INC_ACT_PENDING;
6903             if (plci->B3_prot == 4)
6904               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6905             else
6906               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6907             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6908           }
6909           break;
6910
6911         case EDATA_T30_TRAIN_OK:
6912           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6913            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6914            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6915           {
6916             if (plci->B3_prot == 4)
6917               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6918             else
6919               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6920             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6921           }
6922           break;
6923
6924         case EDATA_T30_EOP_CAPI:
6925           if (a->ncci_state[ncci] == CONNECTED)
6926           {
6927             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6928             a->ncci_state[ncci] = INC_DIS_PENDING;
6929             plci->ncpi_state = 0;
6930      fax_send_edata_ack = false;
6931           }
6932           break;
6933         }
6934       }
6935       else
6936       {
6937         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6938         {
6939         case EDATA_T30_TRAIN_OK:
6940           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6941            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6942            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6943           {
6944             if (plci->B3_prot == 4)
6945               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6946             else
6947               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6948             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6949           }
6950           break;
6951         }
6952       }
6953       if (fax_send_edata_ack)
6954       {
6955         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6956  plci->fax_edata_ack_length = 1;
6957         start_internal_command (Id, plci, fax_edata_ack_command);
6958       }
6959     }
6960     else
6961     {
6962       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6963     }
6964     break;
6965   case N_CONNECT:
6966     if (!a->ch_ncci[ch])
6967     {
6968       ncci = get_ncci (plci, ch, 0);
6969       Id = (Id & 0xffff) | (((dword) ncci) << 16);
6970     }
6971     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6972       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6973
6974     msg = _CONNECT_B3_I;
6975     if (a->ncci_state[ncci] == IDLE)
6976       plci->channels++;
6977     else if (plci->B3_prot == 1)
6978       msg = _CONNECT_B3_T90_ACTIVE_I;
6979
6980     a->ncci_state[ncci] = INC_CON_PENDING;
6981     if(plci->B3_prot == 4)
6982       sendf(plci->appl,msg,Id,0,"s","");
6983     else
6984       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6985     break;
6986   case N_CONNECT_ACK:
6987     dbug(1,dprintf("N_connect_Ack"));
6988     if (plci->internal_command_queue[0]
6989      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6990       || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6991       || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6992     {
6993       (*(plci->internal_command_queue[0]))(Id, plci, 0);
6994       if (!plci->internal_command)
6995         next_internal_command (Id, plci);
6996       break;
6997     }
6998     msg = _CONNECT_B3_ACTIVE_I;
6999     if (plci->B3_prot == 1)
7000     {
7001       if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7002         msg = _CONNECT_B3_T90_ACTIVE_I;
7003       a->ncci_state[ncci] = INC_ACT_PENDING;
7004       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7005     }
7006     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7007     {
7008       if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7009        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7010        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7011       {
7012         a->ncci_state[ncci] = INC_ACT_PENDING;
7013         if (plci->B3_prot == 4)
7014           sendf(plci->appl,msg,Id,0,"s","");
7015         else
7016           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7017         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7018       }
7019     }
7020     else
7021     {
7022       a->ncci_state[ncci] = INC_ACT_PENDING;
7023       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7024     }
7025     if (plci->adjust_b_restore)
7026     {
7027       plci->adjust_b_restore = false;
7028       start_internal_command (Id, plci, adjust_b_restore);
7029     }
7030     break;
7031   case N_DISC:
7032   case N_DISC_ACK:
7033     if (plci->internal_command_queue[0]
7034      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7035       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7036       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7037     {
7038       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7039       if (!plci->internal_command)
7040         next_internal_command (Id, plci);
7041     }
7042     ncci_state = a->ncci_state[ncci];
7043     ncci_remove (plci, ncci, false);
7044
7045         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7046         /* channel, so we cannot store the state in ncci_state! The */
7047         /* information which channel we received a N_DISC is thus   */
7048         /* stored in the inc_dis_ncci_table buffer.                 */
7049     for(i=0; plci->inc_dis_ncci_table[i]; i++);
7050     plci->inc_dis_ncci_table[i] = (byte) ncci;
7051
7052       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7053     if (!plci->channels
7054      && (plci->B1_resource == 16)
7055      && (plci->State <= CONNECTED))
7056     {
7057       len = 9;
7058       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7059       PUT_WORD (&plci->ncpi_buffer[1], i);
7060       PUT_WORD (&plci->ncpi_buffer[3], 0);
7061       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7062       PUT_WORD (&plci->ncpi_buffer[5], i);
7063       PUT_WORD (&plci->ncpi_buffer[7], 0);
7064       plci->ncpi_buffer[len] = 0;
7065       plci->ncpi_buffer[0] = len;
7066       if(plci->B3_prot == 4)
7067         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7068       else
7069       {
7070
7071         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7072           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7073         {
7074           plci->ncpi_buffer[++len] = 0;
7075           plci->ncpi_buffer[++len] = 0;
7076           plci->ncpi_buffer[++len] = 0;
7077           plci->ncpi_buffer[0] = len;
7078         }
7079
7080         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7081       }
7082       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7083       plci->ncpi_state = 0;
7084       sig_req(plci,HANGUP,0);
7085       send_req(plci);
7086       plci->State = OUTG_DIS_PENDING;
7087       /* disc here */
7088     }
7089     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7090      && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7091      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7092     {
7093       if (ncci_state == IDLE)
7094       {
7095         if (plci->channels)
7096           plci->channels--;
7097         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7098           if(plci->State == SUSPENDING){
7099             sendf(plci->appl,
7100                   _FACILITY_I,
7101                   Id & 0xffffL,
7102                   0,
7103                   "ws", (word)3, "\x03\x04\x00\x00");
7104             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7105           }
7106           plci_remove(plci);
7107           plci->State=IDLE;
7108         }
7109       }
7110     }
7111     else if (plci->channels)
7112     {
7113       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7114       plci->ncpi_state = 0;
7115       if ((ncci_state == OUTG_REJ_PENDING)
7116        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7117       {
7118         sig_req(plci,HANGUP,0);
7119         send_req(plci);
7120         plci->State = OUTG_DIS_PENDING;
7121       }
7122     }
7123     break;
7124   case N_RESET:
7125     a->ncci_state[ncci] = INC_RES_PENDING;
7126     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7127     break;
7128   case N_RESET_ACK:
7129     a->ncci_state[ncci] = CONNECTED;
7130     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7131     break;
7132
7133   case N_UDATA:
7134     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7135     {
7136       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7137       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7138       plci->NL.R = plci->RData;
7139       plci->NL.RNum = 1;
7140       return;
7141     }
7142   case N_BDATA:
7143   case N_DATA:
7144     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7145      || (a->ncci_state[ncci] == IDLE)
7146      || (a->ncci_state[ncci] == INC_DIS_PENDING))
7147     {
7148       plci->NL.RNR = 2;
7149       break;
7150     }
7151     if ((a->ncci_state[ncci] != CONNECTED)
7152      && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7153      && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7154     {
7155       dbug(1,dprintf("flow control"));
7156       plci->NL.RNR = 1; /* flow control  */
7157       channel_x_off (plci, ch, 0);
7158       break;
7159     }
7160
7161     NCCIcode = ncci | (((word)a->Id) << 8);
7162
7163                 /* count all buffers within the Application pool    */
7164                 /* belonging to the same NCCI. If this is below the */
7165                 /* number of buffers available per NCCI we accept   */
7166                 /* this packet, otherwise we reject it              */
7167     count = 0;
7168     Num = 0xffff;
7169     for(i=0; i<APPLptr->MaxBuffer; i++) {
7170       if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7171       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7172     }
7173
7174     if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7175     {
7176       dbug(3,dprintf("Flow-Control"));
7177       plci->NL.RNR = 1;
7178       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7179        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7180       {
7181         plci->NL.RNR = 2;
7182         dbug(3,dprintf("DiscardData"));
7183       } else {
7184         channel_x_off (plci, ch, 0);
7185       }
7186       break;
7187     }
7188     else
7189     {
7190       APPLptr->NCCIDataFlowCtrlTimer = 0;
7191     }
7192
7193     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7194     if(!plci->RData[0].P) {
7195       plci->NL.RNR = 1;
7196       channel_x_off (plci, ch, 0);
7197       break;
7198     }
7199
7200     APPLptr->DataNCCI[Num] = NCCIcode;
7201     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7202     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7203
7204     plci->RNum = Num;
7205     plci->RFlags = plci->NL.Ind>>4;
7206     plci->RData[0].PLength = APPLptr->MaxDataLength;
7207     plci->NL.R = plci->RData;
7208     if ((plci->NL.RLength != 0)
7209      && ((plci->B2_prot == B2_V120_ASYNC)
7210       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7211       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7212     {
7213       plci->RData[1].P = plci->RData[0].P;
7214       plci->RData[1].PLength = plci->RData[0].PLength;
7215       plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7216       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7217         plci->RData[0].PLength = 1;
7218       else
7219         plci->RData[0].PLength = 2;
7220       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7221         plci->RFlags |= 0x0010;
7222       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7223         plci->RFlags |= 0x8000;
7224       plci->NL.RNum = 2;
7225     }
7226     else
7227     {
7228       if((plci->NL.Ind &0x0f)==N_UDATA)
7229         plci->RFlags |= 0x0010;
7230
7231       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7232         plci->RFlags |= 0x0001;
7233
7234       plci->NL.RNum = 1;
7235     }
7236     break;
7237   case N_DATA_ACK:
7238     data_ack (plci, ch);
7239     break;
7240   default:
7241     plci->NL.RNR = 2;
7242     break;
7243   }
7244 }
7245
7246 /*------------------------------------------------------------------*/
7247 /* find a free PLCI                                                 */
7248 /*------------------------------------------------------------------*/
7249
7250 word get_plci(DIVA_CAPI_ADAPTER   * a)
7251 {
7252   word i,j;
7253   PLCI   * plci;
7254
7255   dump_plcis (a);
7256   for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7257   if(i==a->max_plci) {
7258     dbug(1,dprintf("get_plci: out of PLCIs"));
7259     return 0;
7260   }
7261   plci = &a->plci[i];
7262   plci->Id = (byte)(i+1);
7263
7264   plci->Sig.Id = 0;
7265   plci->NL.Id = 0;
7266   plci->sig_req = 0;
7267   plci->nl_req = 0;
7268
7269   plci->appl = NULL;
7270   plci->relatedPTYPLCI = NULL;
7271   plci->State = IDLE;
7272   plci->SuppState = IDLE;
7273   plci->channels = 0;
7274   plci->tel = 0;
7275   plci->B1_resource = 0;
7276   plci->B2_prot = 0;
7277   plci->B3_prot = 0;
7278
7279   plci->command = 0;
7280   plci->m_command = 0;
7281   init_internal_command_queue (plci);
7282   plci->number = 0;
7283   plci->req_in_start = 0;
7284   plci->req_in = 0;
7285   plci->req_out = 0;
7286   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7287   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7288   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7289
7290   plci->data_sent = false;
7291   plci->send_disc = 0;
7292   plci->sig_global_req = 0;
7293   plci->sig_remove_id = 0;
7294   plci->nl_global_req = 0;
7295   plci->nl_remove_id = 0;
7296   plci->adv_nl = 0;
7297   plci->manufacturer = false;
7298   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7299   plci->spoofed_msg = 0;
7300   plci->ptyState = 0;
7301   plci->cr_enquiry = false;
7302   plci->hangup_flow_ctrl_timer = 0;
7303
7304   plci->ncci_ring_list = 0;
7305   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7306   clear_c_ind_mask (plci);
7307   set_group_ind_mask (plci);
7308   plci->fax_connect_info_length = 0;
7309   plci->nsf_control_bits = 0;
7310   plci->ncpi_state = 0x00;
7311   plci->ncpi_buffer[0] = 0;
7312
7313   plci->requested_options_conn = 0;
7314   plci->requested_options = 0;
7315   plci->notifiedcall = 0;
7316   plci->vswitchstate = 0;
7317   plci->vsprot = 0;
7318   plci->vsprotdialect = 0;
7319   init_b1_config (plci);
7320   dbug(1,dprintf("get_plci(%x)",plci->Id));
7321   return i+1;
7322 }
7323
7324 /*------------------------------------------------------------------*/
7325 /* put a parameter in the parameter buffer                          */
7326 /*------------------------------------------------------------------*/
7327
7328 static void add_p(PLCI   * plci, byte code, byte   * p)
7329 {
7330   word p_length;
7331
7332   p_length = 0;
7333   if(p) p_length = p[0];
7334   add_ie(plci, code, p, p_length);
7335 }
7336
7337 /*------------------------------------------------------------------*/
7338 /* put a structure in the parameter buffer                          */
7339 /*------------------------------------------------------------------*/
7340 static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7341 {
7342   if(p) add_ie(plci, code, p->info, (word)p->length);
7343 }
7344
7345 /*------------------------------------------------------------------*/
7346 /* put multiple structures in the parameter buffer                  */
7347 /*------------------------------------------------------------------*/
7348 static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7349 {
7350   byte i;
7351
7352   if(p){
7353     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7354     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7355       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7356       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7357     }
7358   }
7359 }
7360
7361 /*------------------------------------------------------------------*/
7362 /* return the channel number sent by the application in a esc_chi   */
7363 /*------------------------------------------------------------------*/
7364 static byte getChannel(API_PARSE * p)
7365 {
7366   byte i;
7367
7368   if(p){
7369     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7370       if(p->info[i]==2){
7371         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7372       }
7373     }
7374   }
7375   return 0;
7376 }
7377
7378
7379 /*------------------------------------------------------------------*/
7380 /* put an information element in the parameter buffer               */
7381 /*------------------------------------------------------------------*/
7382
7383 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7384 {
7385   word i;
7386
7387   if(!(code &0x80) && !p_length) return;
7388
7389   if(plci->req_in==plci->req_in_start) {
7390     plci->req_in +=2;
7391   }
7392   else {
7393     plci->req_in--;
7394   }
7395   plci->RBuffer[plci->req_in++] = code;
7396
7397   if(p) {
7398     plci->RBuffer[plci->req_in++] = (byte)p_length;
7399     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7400   }
7401
7402   plci->RBuffer[plci->req_in++] = 0;
7403 }
7404
7405 /*------------------------------------------------------------------*/
7406 /* put a unstructured data into the buffer                          */
7407 /*------------------------------------------------------------------*/
7408
7409 void add_d(PLCI   * plci, word length, byte   * p)
7410 {
7411   word i;
7412
7413   if(plci->req_in==plci->req_in_start) {
7414     plci->req_in +=2;
7415   }
7416   else {
7417     plci->req_in--;
7418   }
7419   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7420 }
7421
7422 /*------------------------------------------------------------------*/
7423 /* put parameters from the Additional Info parameter in the         */
7424 /* parameter buffer                                                 */
7425 /*------------------------------------------------------------------*/
7426
7427 void add_ai(PLCI   * plci, API_PARSE * ai)
7428 {
7429   word i;
7430     API_PARSE ai_parms[5];
7431
7432   for(i=0;i<5;i++) ai_parms[i].length = 0;
7433
7434   if(!ai->length)
7435     return;
7436   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7437     return;
7438
7439   add_s (plci,KEY,&ai_parms[1]);
7440   add_s (plci,UUI,&ai_parms[2]);
7441   add_ss(plci,FTY,&ai_parms[3]);
7442 }
7443
7444 /*------------------------------------------------------------------*/
7445 /* put parameter for b1 protocol in the parameter buffer            */
7446 /*------------------------------------------------------------------*/
7447
7448 word add_b1(PLCI   * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7449 {
7450     API_PARSE bp_parms[8];
7451     API_PARSE mdm_cfg[9];
7452     API_PARSE global_config[2];
7453     byte cai[256];
7454   byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7455   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7456   word i;
7457
7458     API_PARSE mdm_cfg_v18[4];
7459   word j, n, w;
7460   dword d;
7461
7462
7463   for(i=0;i<8;i++) bp_parms[i].length = 0;
7464   for(i=0;i<2;i++) global_config[i].length = 0;
7465
7466   dbug(1,dprintf("add_b1"));
7467   api_save_msg(bp, "s", &plci->B_protocol);
7468
7469   if(b_channel_info==2){
7470     plci->B1_resource = 0;
7471     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7472     add_p(plci, CAI, "\x01\x00");
7473     dbug(1,dprintf("Cai=1,0 (no resource)"));
7474     return 0;
7475   }
7476
7477   if(plci->tel == CODEC_PERMANENT) return 0;
7478   else if(plci->tel == CODEC){
7479     plci->B1_resource = 1;
7480     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7481     add_p(plci, CAI, "\x01\x01");
7482     dbug(1,dprintf("Cai=1,1 (Codec)"));
7483     return 0;
7484   }
7485   else if(plci->tel == ADV_VOICE){
7486     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7487     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7488     voice_cai[1] = plci->B1_resource;
7489     PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7490     add_p(plci, CAI, voice_cai);
7491     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7492     return 0;
7493   }
7494   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7495   if (plci->call_dir & CALL_DIR_OUT)
7496     plci->call_dir |= CALL_DIR_ORIGINATE;
7497   else if (plci->call_dir & CALL_DIR_IN)
7498     plci->call_dir |= CALL_DIR_ANSWER;
7499
7500   if(!bp->length){
7501     plci->B1_resource = 0x5;
7502     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7503     add_p(plci, CAI, "\x01\x05");
7504     return 0;
7505   }
7506
7507   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7508   if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7509   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7510   {
7511     bp_parms[6].length = 0;
7512     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7513     {
7514       dbug(1,dprintf("b-form.!"));
7515       return _WRONG_MESSAGE_FORMAT;
7516     }
7517   }
7518   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7519   {
7520     dbug(1,dprintf("b-form.!"));
7521     return _WRONG_MESSAGE_FORMAT;
7522   }
7523
7524   if(bp_parms[6].length)
7525   {
7526     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7527     {
7528       return _WRONG_MESSAGE_FORMAT;
7529     }
7530     switch(GET_WORD(global_config[0].info))
7531     {
7532     case 1:
7533       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7534       break;
7535     case 2:
7536       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7537       break;
7538     }
7539   }
7540   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7541
7542
7543   if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7544    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7545   {
7546     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7547     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7548     cai[1] = plci->B1_resource;
7549     cai[2] = 0;
7550     cai[3] = 0;
7551     cai[4] = 0;
7552     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7553     for (i = 0; i < bp_parms[3].length; i++)
7554       cai[7+i] = bp_parms[3].info[1+i];
7555     cai[0] = 6 + bp_parms[3].length;
7556     add_p(plci, CAI, cai);
7557     return 0;
7558   }
7559
7560
7561   if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7562    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7563   {
7564     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7565     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566     cai[1] = plci->B1_resource;
7567     cai[2] = 0;
7568     cai[3] = 0;
7569     cai[4] = 0;
7570     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7571     cai[0] = 6;
7572     add_p(plci, CAI, cai);
7573     return 0;
7574   }
7575
7576
7577   if ((GET_WORD(bp_parms[0].info) >= 32)
7578    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7579     && ((GET_WORD(bp_parms[0].info) != 3)
7580      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7581      || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7582   {
7583     return _B1_NOT_SUPPORTED;
7584   }
7585   plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7586     (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7588   cai[0] = 6;
7589   cai[1] = plci->B1_resource;
7590   for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7591
7592   if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7593    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7594    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7595   { /* B1 - modem */
7596     for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7597
7598     if (bp_parms[3].length)
7599     {
7600       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7601       {
7602         return (_WRONG_MESSAGE_FORMAT);
7603       }
7604         
7605       cai[2] = 0; /* Bit rate for adaptation */
7606
7607       dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7608
7609       PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
7610       PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7611       PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
7612       PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7613
7614       cai[3] = 0; /* Async framing parameters */
7615       switch (GET_WORD (mdm_cfg[2].info))
7616       {       /* Parity     */
7617       case 1: /* odd parity */
7618         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7619         dbug(1,dprintf("MDM: odd parity"));
7620         break;
7621
7622       case 2: /* even parity */
7623         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7624         dbug(1,dprintf("MDM: even parity"));
7625         break;
7626
7627       default:
7628         dbug(1,dprintf("MDM: no parity"));
7629         break;
7630       }
7631
7632       switch (GET_WORD (mdm_cfg[3].info))
7633       {       /* stop bits   */
7634       case 1: /* 2 stop bits */
7635         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7636         dbug(1,dprintf("MDM: 2 stop bits"));
7637         break;
7638
7639       default:
7640         dbug(1,dprintf("MDM: 1 stop bit"));
7641         break;
7642       }
7643
7644       switch (GET_WORD (mdm_cfg[1].info))
7645       {     /* char length */
7646       case 5:
7647         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7648         dbug(1,dprintf("MDM: 5 bits"));
7649         break;
7650
7651       case 6:
7652         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7653         dbug(1,dprintf("MDM: 6 bits"));
7654         break;
7655
7656       case 7:
7657         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7658         dbug(1,dprintf("MDM: 7 bits"));
7659         break;
7660
7661       default:
7662         dbug(1,dprintf("MDM: 8 bits"));
7663         break;
7664       }
7665
7666       cai[7] = 0; /* Line taking options */
7667       cai[8] = 0; /* Modulation negotiation options */
7668       cai[9] = 0; /* Modulation options */
7669
7670       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7671       {
7672         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7673         dbug(1, dprintf("MDM: Reverse direction"));
7674       }
7675
7676       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7677       {
7678         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7679         dbug(1, dprintf("MDM: Disable retrain"));
7680       }
7681
7682       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7683       {
7684         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7685         dbug(1, dprintf("MDM: Disable ring tone"));
7686       }
7687
7688       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7689       {
7690         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7691         dbug(1, dprintf("MDM: 1800 guard tone"));
7692       }
7693       else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7694       {
7695         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7696         dbug(1, dprintf("MDM: 550 guard tone"));
7697       }
7698
7699       if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7700       {
7701         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7702         dbug(1, dprintf("MDM: V100"));
7703       }
7704       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7705       {
7706         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7707         dbug(1, dprintf("MDM: IN CLASS"));
7708       }
7709       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7710       {
7711         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7712         dbug(1, dprintf("MDM: DISABLED"));
7713       }
7714       cai[0] = 20;
7715
7716       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7717        && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7718       {
7719         plci->requested_options |= 1L << PRIVATE_V18;
7720       }
7721       if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7722         plci->requested_options |= 1L << PRIVATE_VOWN;
7723
7724       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7725         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7726       {
7727         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7728         {
7729           i = 27;
7730           if (mdm_cfg[6].length >= 4)
7731           {
7732             d = GET_DWORD(&mdm_cfg[6].info[1]);
7733             cai[7] |= (byte) d;          /* line taking options */
7734             cai[9] |= (byte)(d >> 8);    /* modulation options */
7735             cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7736             cai[++i] = (byte)(d >> 24);
7737             if (mdm_cfg[6].length >= 8)
7738             {
7739               d = GET_DWORD(&mdm_cfg[6].info[5]);
7740               cai[10] |= (byte) d;        /* disabled modulations mask */
7741               cai[11] |= (byte)(d >> 8);
7742               if (mdm_cfg[6].length >= 12)
7743               {
7744                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7745                 cai[12] = (byte) d;          /* enabled modulations mask */
7746                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7747                 cai[++i] = (byte)(d >> 16);
7748                 cai[++i] = (byte)(d >> 24);
7749                 cai[++i] = 0;
7750                 if (mdm_cfg[6].length >= 14)
7751                 {
7752                   w = GET_WORD(&mdm_cfg[6].info[13]);
7753                   if (w != 0)
7754                     PUT_WORD(&cai[13], w);  /* min tx speed */
7755                   if (mdm_cfg[6].length >= 16)
7756                   {
7757                     w = GET_WORD(&mdm_cfg[6].info[15]);
7758                     if (w != 0)
7759                       PUT_WORD(&cai[15], w);  /* max tx speed */
7760                     if (mdm_cfg[6].length >= 18)
7761                     {
7762                       w = GET_WORD(&mdm_cfg[6].info[17]);
7763                       if (w != 0)
7764                         PUT_WORD(&cai[17], w);  /* min rx speed */
7765                       if (mdm_cfg[6].length >= 20)
7766                       {
7767                         w = GET_WORD(&mdm_cfg[6].info[19]);
7768                         if (w != 0)
7769                           PUT_WORD(&cai[19], w);  /* max rx speed */
7770                         if (mdm_cfg[6].length >= 22)
7771                         {
7772                           w = GET_WORD(&mdm_cfg[6].info[21]);
7773                           cai[23] = (byte)(-((short) w));  /* transmit level */
7774                           if (mdm_cfg[6].length >= 24)
7775                           {
7776                             w = GET_WORD(&mdm_cfg[6].info[23]);
7777                             cai[22] |= (byte) w;        /* info options mask */
7778                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7779                           }
7780                         }
7781                       }
7782                     }
7783                   }
7784                 }
7785               }
7786             }
7787           }
7788           cai[27] = i - 27;
7789           i++;
7790           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7791           {
7792             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7793             {
7794               for (n = 0; n < 3; n++)
7795               {
7796                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7797                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7798                   cai[i+j] = mdm_cfg_v18[n].info[j];
7799                 i += cai[i] + 1;
7800               }
7801             }
7802           }
7803           cai[0] = (byte)(i - 1);
7804         }
7805       }
7806
7807     }
7808   }
7809   if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
7810      GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
7811   {
7812     if(bp_parms[3].length){
7813       dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7814       switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
7815         case 0:
7816         case 56000:
7817           if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
7818             dbug(1,dprintf("56k sync HSCX"));
7819             cai[1] = 8;
7820             cai[2] = 0;
7821             cai[3] = 0;
7822           }
7823           else if(GET_WORD(bp_parms[0].info)==2){
7824             dbug(1,dprintf("56k async DSP"));
7825             cai[2] = 9;
7826           }
7827           break;
7828         case 50:     cai[2] = 1;  break;
7829         case 75:     cai[2] = 1;  break;
7830         case 110:    cai[2] = 1;  break;
7831         case 150:    cai[2] = 1;  break;
7832         case 200:    cai[2] = 1;  break;
7833         case 300:    cai[2] = 1;  break;
7834         case 600:    cai[2] = 1;  break;
7835         case 1200:   cai[2] = 2;  break;
7836         case 2400:   cai[2] = 3;  break;
7837         case 4800:   cai[2] = 4;  break;
7838         case 7200:   cai[2] = 10; break;
7839         case 9600:   cai[2] = 5;  break;
7840         case 12000:  cai[2] = 13; break;
7841         case 24000:  cai[2] = 0;  break;
7842         case 14400:  cai[2] = 11; break;
7843         case 19200:  cai[2] = 6;  break;
7844         case 28800:  cai[2] = 12; break;
7845         case 38400:  cai[2] = 7;  break;
7846         case 48000:  cai[2] = 8;  break;
7847         case 76:     cai[2] = 15; break;  /* 75/1200     */
7848         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7849         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7850
7851         default:
7852           return _B1_PARM_NOT_SUPPORTED;
7853       }
7854       cai[3] = 0;
7855       if (cai[1] == 13)                                        /* v.110 async */
7856       {
7857         if (bp_parms[3].length >= 8)
7858         {
7859           switch (GET_WORD (&bp_parms[3].info[3]))
7860           {       /* char length */
7861           case 5:
7862             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7863             break;
7864           case 6:
7865             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7866             break;
7867           case 7:
7868             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7869             break;
7870           }
7871           switch (GET_WORD (&bp_parms[3].info[5]))
7872           {       /* Parity     */
7873           case 1: /* odd parity */
7874             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7875             break;
7876           case 2: /* even parity */
7877             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7878             break;
7879           }
7880           switch (GET_WORD (&bp_parms[3].info[7]))
7881           {       /* stop bits   */
7882           case 1: /* 2 stop bits */
7883             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7884             break;
7885           }
7886         }
7887       }
7888     }
7889     else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7890       dbug(1,dprintf("V.110 default 56k sync"));
7891       cai[1] = 8;
7892       cai[2] = 0;
7893       cai[3] = 0;
7894     }
7895     else {
7896       dbug(1,dprintf("V.110 default 9600 async"));
7897       cai[2] = 5;
7898     }
7899   }
7900   PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7901   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]));
7902 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7903
7904   add_p(plci, CAI, cai);
7905   return 0;
7906 }
7907
7908 /*------------------------------------------------------------------*/
7909 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7910 /*------------------------------------------------------------------*/
7911
7912 word add_b23(PLCI   * plci, API_PARSE * bp)
7913 {
7914   word i, fax_control_bits;
7915   byte pos, len;
7916   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7917     API_PARSE bp_parms[8];
7918   API_PARSE * b1_config;
7919   API_PARSE * b2_config;
7920     API_PARSE b2_config_parms[8];
7921   API_PARSE * b3_config;
7922     API_PARSE b3_config_parms[6];
7923     API_PARSE global_config[2];
7924
7925   static byte llc[3] = {2,0,0};
7926   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7927   static byte nlc[256];
7928   static byte lli[12] = {1,1};
7929
7930   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7931   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7932
7933   const byte llc3[] = {4,3,2,2,6,6,0};
7934   const byte header[] = {0,2,3,3,0,0,0};
7935
7936   for(i=0;i<8;i++) bp_parms[i].length = 0;
7937   for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7938   for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7939
7940   lli[0] = 1;
7941   lli[1] = 1;
7942   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7943     lli[1] |= 2;
7944   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7945     lli[1] |= 4;
7946
7947   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7948     lli[1] |= 0x10;
7949     if (plci->rx_dma_descriptor <= 0) {
7950       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7951       if (plci->rx_dma_descriptor >= 0)
7952         plci->rx_dma_descriptor++;
7953     }
7954     if (plci->rx_dma_descriptor > 0) {
7955       lli[0] = 6;
7956       lli[1] |= 0x40;
7957       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7958       lli[3] = (byte)plci->rx_dma_magic;
7959       lli[4] = (byte)(plci->rx_dma_magic >>  8);
7960       lli[5] = (byte)(plci->rx_dma_magic >> 16);
7961       lli[6] = (byte)(plci->rx_dma_magic >> 24);
7962     }
7963   }
7964
7965   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7966     lli[1] |= 0x20;
7967   }
7968
7969   dbug(1,dprintf("add_b23"));
7970   api_save_msg(bp, "s", &plci->B_protocol);
7971
7972   if(!bp->length && plci->tel)
7973   {
7974     plci->adv_nl = true;
7975     dbug(1,dprintf("Default adv.Nl"));
7976     add_p(plci,LLI,lli);
7977     plci->B2_prot = 1 /*XPARENT*/;
7978     plci->B3_prot = 0 /*XPARENT*/;
7979     llc[1] = 2;
7980     llc[2] = 4;
7981     add_p(plci, LLC, llc);
7982     dlc[0] = 2;
7983     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7984     add_p(plci, DLC, dlc);
7985     return 0;
7986   }
7987
7988   if(!bp->length) /*default*/
7989   {   
7990     dbug(1,dprintf("ret default"));
7991     add_p(plci,LLI,lli);
7992     plci->B2_prot = 0 /*X.75   */;
7993     plci->B3_prot = 0 /*XPARENT*/;
7994     llc[1] = 1;
7995     llc[2] = 4;
7996     add_p(plci, LLC, llc);
7997     dlc[0] = 2;
7998     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7999     add_p(plci, DLC, dlc);
8000     return 0;
8001   }
8002   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8003   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8004
8005   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8006   {
8007     bp_parms[6].length = 0;
8008     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8009     {
8010       dbug(1,dprintf("b-form.!"));
8011       return _WRONG_MESSAGE_FORMAT;
8012     }
8013   }
8014   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8015   {
8016     dbug(1,dprintf("b-form.!"));
8017     return _WRONG_MESSAGE_FORMAT;
8018   }
8019
8020   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8021   {  
8022     if(GET_WORD(bp_parms[1].info)!=1
8023     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8024     plci->adv_nl = true;
8025   }
8026   else if(plci->tel) return _B2_NOT_SUPPORTED;
8027
8028
8029   if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8030    && (GET_WORD(bp_parms[2].info) == B3_RTP)
8031    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8032   {
8033     add_p(plci,LLI,lli);
8034     plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8035     plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8036     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8037     llc[2] = 4;
8038     add_p(plci, LLC, llc);
8039     dlc[0] = 2;
8040     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8041     dlc[3] = 3; /* Addr A */
8042     dlc[4] = 1; /* Addr B */
8043     dlc[5] = 7; /* modulo mode */
8044     dlc[6] = 7; /* window size */
8045     dlc[7] = 0; /* XID len Lo  */
8046     dlc[8] = 0; /* XID len Hi  */
8047     for (i = 0; i < bp_parms[4].length; i++)
8048       dlc[9+i] = bp_parms[4].info[1+i];
8049     dlc[0] = (byte)(8 + bp_parms[4].length);
8050     add_p(plci, DLC, dlc);
8051     for (i = 0; i < bp_parms[5].length; i++)
8052       nlc[1+i] = bp_parms[5].info[1+i];
8053     nlc[0] = (byte)(bp_parms[5].length);
8054     add_p(plci, NLC, nlc);
8055     return 0;
8056   }
8057
8058
8059
8060   if ((GET_WORD(bp_parms[1].info) >= 32)
8061    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8062     && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8063      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8064
8065   {
8066     return _B2_NOT_SUPPORTED;
8067   }
8068   if ((GET_WORD(bp_parms[2].info) >= 32)
8069    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8070   {
8071     return _B3_NOT_SUPPORTED;
8072   }
8073   if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8074    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8075     || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8076     || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8077   {
8078     return (add_modem_b23 (plci, bp_parms));
8079   }
8080
8081   add_p(plci,LLI,lli);
8082
8083   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8084   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8085   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8086
8087   if(bp_parms[6].length)
8088   {
8089     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8090     {
8091       return _WRONG_MESSAGE_FORMAT;
8092     }
8093     switch(GET_WORD(global_config[0].info))
8094     {
8095     case 1:
8096       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8097       break;
8098     case 2:
8099       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8100       break;
8101     }
8102   }
8103   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8104
8105
8106   if (plci->B2_prot == B2_PIAFS)
8107     llc[1] = PIAFS_CRC;
8108   else
8109 /* IMPLEMENT_PIAFS */
8110   {
8111     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8112              llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8113   }
8114   llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8115
8116   add_p(plci, LLC, llc);
8117
8118   dlc[0] = 2;
8119   PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8120                       header[GET_WORD(bp_parms[2].info)]);
8121
8122   b1_config = &bp_parms[3];
8123   nlc[0] = 0;
8124   if(plci->B3_prot == 4
8125   || plci->B3_prot == 5)
8126   {
8127     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8128     nlc[0] = sizeof(T30_INFO);
8129     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8130       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8131     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8132     if(b1_config->length>=2)
8133     {
8134       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8135     }
8136   }
8137   b2_config = &bp_parms[4];
8138
8139
8140   if (llc[1] == PIAFS_CRC)
8141   {
8142     if (plci->B3_prot != B3_TRANSPARENT)
8143     {
8144       return _B_STACK_NOT_SUPPORTED;
8145     }
8146     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8147       return _WRONG_MESSAGE_FORMAT;
8148     }
8149     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8150     dlc[3] = 0; /* Addr A */
8151     dlc[4] = 0; /* Addr B */
8152     dlc[5] = 0; /* modulo mode */
8153     dlc[6] = 0; /* window size */
8154     if (b2_config->length >= 7){
8155       dlc[ 7] = 7; 
8156       dlc[ 8] = 0; 
8157       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8158       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8159       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8160       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8161       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8162       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8163       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8164       dlc[ 0] = 15;
8165       if(b2_config->length >= 8) { /* PIAFS control abilities */
8166         dlc[ 7] = 10; 
8167         dlc[16] = 2; /* Length of PIAFS extention */
8168         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8169         dlc[18] = b2_config_parms[4].info[0]; /* value */
8170         dlc[ 0] = 18;
8171       }
8172     }
8173     else /* default values, 64K, variable, no compression */
8174     {
8175       dlc[ 7] = 7; 
8176       dlc[ 8] = 0; 
8177       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8178       dlc[10] = 0x03; /* V.42bis P0 */
8179       dlc[11] = 0;    /* V.42bis P0 */
8180       dlc[12] = 0;    /* V.42bis P1 */
8181       dlc[13] = 0;    /* V.42bis P1 */
8182       dlc[14] = 0;    /* V.42bis P2 */
8183       dlc[15] = 0;    /* V.42bis P2 */
8184     dlc[ 0] = 15;
8185     }
8186     add_p(plci, DLC, dlc);
8187   }
8188   else
8189
8190   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8191   {
8192     if (plci->B3_prot != B3_TRANSPARENT)
8193       return _B_STACK_NOT_SUPPORTED;
8194
8195     dlc[0] = 6;
8196     PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8197     dlc[3] = 0x08;
8198     dlc[4] = 0x01;
8199     dlc[5] = 127;
8200     dlc[6] = 7;
8201     if (b2_config->length != 0)
8202     {
8203       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8204         return _WRONG_MESSAGE_FORMAT;
8205       }
8206       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8207       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8208       if (b2_config->info[3] != 128)
8209       {
8210         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8211         return _B2_PARM_NOT_SUPPORTED;
8212       }
8213       dlc[5] = (byte)(b2_config->info[3] - 1);
8214       dlc[6] = b2_config->info[4];
8215       if(llc[1]==V120_V42BIS){
8216         if (b2_config->length >= 10){
8217           dlc[ 7] = 6; 
8218           dlc[ 8] = 0; 
8219           dlc[ 9] = b2_config_parms[4].info[0];
8220           dlc[10] = b2_config_parms[4].info[1];
8221           dlc[11] = b2_config_parms[5].info[0];
8222           dlc[12] = b2_config_parms[5].info[1];
8223           dlc[13] = b2_config_parms[6].info[0];
8224           dlc[14] = b2_config_parms[6].info[1];
8225           dlc[ 0] = 14;
8226           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8227           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8228           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8229         }
8230         else {
8231           dlc[ 6] = 14;
8232         }
8233       }
8234     }
8235   }
8236   else
8237   {
8238     if(b2_config->length)
8239     {
8240       dbug(1,dprintf("B2-Config"));
8241       if(llc[1]==X75_V42BIS){
8242         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8243         {
8244           return _WRONG_MESSAGE_FORMAT;
8245         }
8246       }
8247       else {
8248         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8249         {
8250           return _WRONG_MESSAGE_FORMAT;
8251         }
8252       }
8253           /* if B2 Protocol is LAPD, b2_config structure is different */
8254       if(llc[1]==6)
8255       {
8256         dlc[0] = 4;
8257         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8258         else dlc[2] = 0x01;
8259         if( (b2_config->length>=2) && (plci->B2_prot==12) )
8260         {
8261           SAPI = b2_config->info[2];    /* SAPI */
8262         }
8263         dlc[1] = SAPI;
8264         if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8265         {
8266           dlc[3] = 127;      /* Mode */
8267         }
8268         else
8269         {
8270           dlc[3] = 7;        /* Mode */
8271         }
8272    
8273         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8274         else dlc[4] = 1;
8275         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8276         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8277       }
8278       else
8279       {
8280         dlc[0] = (byte)(b2_config_parms[4].length+6);
8281         dlc[3] = b2_config->info[1];
8282         dlc[4] = b2_config->info[2];
8283         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8284           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8285           return _B2_PARM_NOT_SUPPORTED;
8286         }
8287
8288         dlc[5] = (byte)(b2_config->info[3]-1);
8289         dlc[6] = b2_config->info[4];
8290         if(dlc[6]>dlc[5]){
8291           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]));
8292           return _B2_PARM_NOT_SUPPORTED;
8293         }
8294  
8295         if(llc[1]==X75_V42BIS) {
8296           if (b2_config->length >= 10){
8297             dlc[ 7] = 6; 
8298             dlc[ 8] = 0; 
8299             dlc[ 9] = b2_config_parms[4].info[0];
8300             dlc[10] = b2_config_parms[4].info[1];
8301             dlc[11] = b2_config_parms[5].info[0];
8302             dlc[12] = b2_config_parms[5].info[1];
8303             dlc[13] = b2_config_parms[6].info[0];
8304             dlc[14] = b2_config_parms[6].info[1];
8305             dlc[ 0] = 14;
8306             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8307             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8308             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8309           }
8310           else {
8311             dlc[ 6] = 14;
8312           }
8313
8314         }
8315         else {
8316           PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8317           for(i=0; i<b2_config_parms[4].length; i++)
8318             dlc[11+i] = b2_config_parms[4].info[1+i];
8319         }
8320       }
8321     }
8322   }
8323   add_p(plci, DLC, dlc);
8324
8325   b3_config = &bp_parms[5];
8326   if(b3_config->length)
8327   {
8328     if(plci->B3_prot == 4 
8329     || plci->B3_prot == 5)
8330     {
8331       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8332       {
8333         return _WRONG_MESSAGE_FORMAT;
8334       }
8335       i = GET_WORD((byte   *)(b3_config_parms[0].info));
8336       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8337         ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8338       ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
8339       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8340       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8341         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8342       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8343       {
8344
8345         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8346           & (1L << PRIVATE_FAX_PAPER_FORMATS))
8347         {
8348           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8349             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8350             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8351         }
8352
8353  ((T30_INFO *)&nlc[1])->recording_properties =
8354    T30_RECORDING_WIDTH_ISO_A3 |
8355    (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8356    (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8357       }
8358       if(plci->B3_prot == 5)
8359       {
8360         if (i & 0x0002) /* Accept incoming fax-polling requests */
8361           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8362         if (i & 0x2000) /* Do not use MR compression */
8363           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8364         if (i & 0x4000) /* Do not use MMR compression */
8365           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8366         if (i & 0x8000) /* Do not use ECM */
8367           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8368         if (plci->fax_connect_info_length != 0)
8369         {
8370           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8371           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8372           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8373           fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8374             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8375         }
8376       }
8377       /* copy station id to NLC */
8378       for(i=0; i<20; i++)
8379       {
8380         if(i<b3_config_parms[2].length)
8381         {
8382           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8383         }
8384         else
8385         {
8386           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8387         }
8388       }
8389       ((T30_INFO *)&nlc[1])->station_id_len = 20;
8390       /* copy head line to NLC */
8391       if(b3_config_parms[3].length)
8392       {
8393
8394         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8395         if (pos != 0)
8396         {
8397           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8398             pos = 0;
8399           else
8400           {
8401             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8402             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8403             len = (byte)b3_config_parms[2].length;
8404             if (len > 20)
8405               len = 20;
8406             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8407             {
8408               for (i = 0; i < len; i++)
8409                 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8410               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8411               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8412             }
8413           }
8414         }
8415
8416         len = (byte)b3_config_parms[3].length;
8417         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8418           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8419         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8420         nlc[0] += (byte)(pos + len);
8421         for (i = 0; i < len; i++)
8422           ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
8423         }
8424       else
8425         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8426
8427       plci->nsf_control_bits = 0;
8428       if(plci->B3_prot == 5)
8429       {
8430         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8431          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8432         {
8433           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8434         }
8435         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8436          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8437         {
8438           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8439         }
8440         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8441           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8442         {
8443         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8444           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8445         {
8446           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8447           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8448             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8449           }
8450             len = nlc[0];
8451           pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8452    if (pos < plci->fax_connect_info_length)
8453    {
8454      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8455               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8456           }
8457    else
8458      nlc[++len] = 0;
8459    if (pos < plci->fax_connect_info_length)
8460    {
8461      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8462               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8463           }
8464    else
8465      nlc[++len] = 0;
8466           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8467             & (1L << PRIVATE_FAX_NONSTANDARD))
8468           {
8469      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8470      {
8471               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8472                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8473        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8474                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8475             }
8476      else
8477      {
8478               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8479               {
8480                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8481                 nlc[++len] = 0;
8482               }
8483        else
8484        {
8485                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8486                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8487          nlc[++len] = (byte)(b3_config_parms[4].length);
8488          for (i = 0; i < b3_config_parms[4].length; i++)
8489     nlc[++len] = b3_config_parms[4].info[1+i];
8490        }
8491             }
8492           }
8493             nlc[0] = len;
8494    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8495     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8496    {
8497             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8498           }
8499         }
8500       }
8501
8502       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8503       len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8504       for (i = 0; i < len; i++)
8505         plci->fax_connect_info_buffer[i] = nlc[1+i];
8506       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8507       i += ((T30_INFO *)&nlc[1])->head_line_len;
8508       while (i < nlc[0])
8509         plci->fax_connect_info_buffer[len++] = nlc[++i];
8510       plci->fax_connect_info_length = len;
8511     }
8512     else
8513     {
8514       nlc[0] = 14;
8515       if(b3_config->length!=16)
8516         return _B3_PARM_NOT_SUPPORTED;
8517       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8518       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8519         return _B3_PARM_NOT_SUPPORTED;
8520       nlc[13] = b3_config->info[13];
8521       if(GET_WORD(&b3_config->info[15])>=nlc[13])
8522         return _B3_PARM_NOT_SUPPORTED;
8523       nlc[14] = b3_config->info[15];
8524     }
8525   }
8526   else
8527   {
8528     if (plci->B3_prot == 4 
8529      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8530   }
8531   add_p(plci, NLC, nlc);
8532   return 0;
8533 }
8534
8535 /*----------------------------------------------------------------*/
8536 /*      make the same as add_b23, but only for the modem related  */
8537 /*      L2 and L3 B-Chan protocol.                                */
8538 /*                                                                */
8539 /*      Enabled L2 and L3 Configurations:                         */
8540 /*        If L1 == Modem all negotiation                          */
8541 /*          only L2 == Modem with full negotiation is allowed     */
8542 /*        If L1 == Modem async or sync                            */
8543 /*          only L2 == Transparent is allowed                     */
8544 /*        L3 == Modem or L3 == Transparent are allowed            */
8545 /*      B2 Configuration for modem:                               */
8546 /*          word : enable/disable compression, bitoptions         */
8547 /*      B3 Configuration for modem:                               */
8548 /*          empty                                                 */
8549 /*----------------------------------------------------------------*/
8550 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8551 {
8552   static byte lli[12] = {1,1};
8553   static byte llc[3] = {2,0,0};
8554   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8555     API_PARSE mdm_config[2];
8556   word i;
8557   word b2_config = 0;
8558
8559   for(i=0;i<2;i++) mdm_config[i].length = 0;
8560   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8561
8562   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8563     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8564    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8565     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8566   {
8567     return (_B_STACK_NOT_SUPPORTED);
8568   }
8569   if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8570    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8571   {
8572     return (_B_STACK_NOT_SUPPORTED);
8573   }
8574
8575   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8576   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8577
8578   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8579   {
8580     if (api_parse (&bp_parms[4].info[1],
8581                   (word)bp_parms[4].length, "w",
8582                   mdm_config))
8583     {
8584       return (_WRONG_MESSAGE_FORMAT);
8585     }
8586     b2_config = GET_WORD(mdm_config[0].info);
8587   }
8588
8589   /* OK, L2 is modem */
8590
8591   lli[0] = 1;
8592   lli[1] = 1;
8593   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8594     lli[1] |= 2;
8595   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8596     lli[1] |= 4;
8597
8598   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8599     lli[1] |= 0x10;
8600     if (plci->rx_dma_descriptor <= 0) {
8601       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8602       if (plci->rx_dma_descriptor >= 0)
8603         plci->rx_dma_descriptor++;
8604     }
8605     if (plci->rx_dma_descriptor > 0) {
8606       lli[1] |= 0x40;
8607       lli[0] = 6;
8608       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8609       lli[3] = (byte)plci->rx_dma_magic;
8610       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8611       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8612       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8613     }
8614   }
8615
8616   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8617     lli[1] |= 0x20;
8618   }
8619
8620   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8621     /*V42*/ 10 : /*V42_IN*/ 9;
8622   llc[2] = 4;                      /* pass L3 always transparent */
8623   add_p(plci, LLI, lli);
8624   add_p(plci, LLC, llc);
8625   i =  1;
8626   PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8627   i += 2;
8628   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8629   {
8630     if (bp_parms[4].length)
8631   {
8632     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8633     dlc[i++] = 3; /* Addr A */
8634     dlc[i++] = 1; /* Addr B */
8635     dlc[i++] = 7; /* modulo mode */
8636     dlc[i++] = 7; /* window size */
8637     dlc[i++] = 0; /* XID len Lo  */
8638     dlc[i++] = 0; /* XID len Hi  */
8639
8640     if (b2_config & MDM_B2_DISABLE_V42bis)
8641     {
8642       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8643     }
8644     if (b2_config & MDM_B2_DISABLE_MNP)
8645     {
8646       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8647     }
8648     if (b2_config & MDM_B2_DISABLE_TRANS)
8649     {
8650       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8651     }
8652     if (b2_config & MDM_B2_DISABLE_V42)
8653     {
8654       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8655     }
8656     if (b2_config & MDM_B2_DISABLE_COMP)
8657     {
8658       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8659     }
8660     i++;
8661   }
8662   }
8663   else
8664   {
8665     dlc[i++] = 3; /* Addr A */
8666     dlc[i++] = 1; /* Addr B */
8667     dlc[i++] = 7; /* modulo mode */
8668     dlc[i++] = 7; /* window size */
8669     dlc[i++] = 0; /* XID len Lo  */
8670     dlc[i++] = 0; /* XID len Hi  */
8671     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8672                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8673                DLC_MODEMPROT_DISABLE_V42_DETECT |
8674                DLC_MODEMPROT_DISABLE_COMPRESSION;
8675   }
8676   dlc[0] = (byte)(i - 1);
8677 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8678   add_p(plci, DLC, dlc);
8679   return (0);
8680 }
8681
8682
8683 /*------------------------------------------------------------------*/
8684 /* send a request for the signaling entity                          */
8685 /*------------------------------------------------------------------*/
8686
8687 void sig_req(PLCI   * plci, byte req, byte Id)
8688 {
8689   if(!plci) return;
8690   if(plci->adapter->adapter_disabled) return;
8691   dbug(1,dprintf("sig_req(%x)",req));
8692   if (req == REMOVE)
8693     plci->sig_remove_id = plci->Sig.Id;
8694   if(plci->req_in==plci->req_in_start) {
8695     plci->req_in +=2;
8696     plci->RBuffer[plci->req_in++] = 0;
8697   }
8698   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8699   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8700   plci->RBuffer[plci->req_in++] = req;  /* request */
8701   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8702   plci->req_in_start = plci->req_in;
8703 }
8704
8705 /*------------------------------------------------------------------*/
8706 /* send a request for the network layer entity                      */
8707 /*------------------------------------------------------------------*/
8708
8709 void nl_req_ncci(PLCI   * plci, byte req, byte ncci)
8710 {
8711   if(!plci) return;
8712   if(plci->adapter->adapter_disabled) return;
8713   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8714   if (req == REMOVE)
8715   {
8716     plci->nl_remove_id = plci->NL.Id;
8717     ncci_remove (plci, 0, (byte)(ncci != 0));
8718     ncci = 0;
8719   }
8720   if(plci->req_in==plci->req_in_start) {
8721     plci->req_in +=2;
8722     plci->RBuffer[plci->req_in++] = 0;
8723   }
8724   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8725   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8726   plci->RBuffer[plci->req_in++] = req;  /* request */
8727   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8728   plci->req_in_start = plci->req_in;
8729 }
8730
8731 void send_req(PLCI   * plci)
8732 {
8733   ENTITY   * e;
8734   word l;
8735 /*  word i; */
8736
8737   if(!plci) return;
8738   if(plci->adapter->adapter_disabled) return;
8739   channel_xmit_xon (plci);
8740
8741         /* if nothing to do, return */
8742   if(plci->req_in==plci->req_out) return;
8743   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8744
8745   if(plci->nl_req || plci->sig_req) return;
8746
8747   l = GET_WORD(&plci->RBuffer[plci->req_out]);
8748   plci->req_out += 2;
8749   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8750   plci->req_out += l;
8751   if(plci->RBuffer[plci->req_out]==1)
8752   {
8753     e = &plci->NL;
8754     plci->req_out++;
8755     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8756     e->ReqCh = plci->RBuffer[plci->req_out++];
8757     if(!(e->Id & 0x1f))
8758     {
8759       e->Id = NL_ID;
8760       plci->RBuffer[plci->req_out-4] = CAI;
8761       plci->RBuffer[plci->req_out-3] = 1;
8762       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8763       plci->RBuffer[plci->req_out-1] = 0;
8764       l+=3;
8765       plci->nl_global_req = plci->nl_req;
8766     }
8767     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8768   }
8769   else
8770   {
8771     e = &plci->Sig;
8772     if(plci->RBuffer[plci->req_out])
8773       e->Id = plci->RBuffer[plci->req_out];
8774     plci->req_out++;
8775     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8776     e->ReqCh = plci->RBuffer[plci->req_out++];
8777     if(!(e->Id & 0x1f))
8778       plci->sig_global_req = plci->sig_req;
8779     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8780   }
8781   plci->XData[0].PLength = l;
8782   e->X = plci->XData;
8783   plci->adapter->request(e);
8784   dbug(1,dprintf("send_ok"));
8785 }
8786
8787 void send_data(PLCI   * plci)
8788 {
8789   DIVA_CAPI_ADAPTER   * a;
8790   DATA_B3_DESC   * data;
8791   NCCI   *ncci_ptr;
8792   word ncci;
8793
8794   if (!plci->nl_req && plci->ncci_ring_list)
8795   {
8796     a = plci->adapter;
8797     ncci = plci->ncci_ring_list;
8798     do
8799     {
8800       ncci = a->ncci_next[ncci];
8801       ncci_ptr = &(a->ncci[ncci]);
8802       if (!(a->ncci_ch[ncci]
8803          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8804       {
8805         if (ncci_ptr->data_pending)
8806         {
8807           if ((a->ncci_state[ncci] == CONNECTED)
8808            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8809            || (plci->send_disc == ncci))
8810           {
8811             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8812             if ((plci->B2_prot == B2_V120_ASYNC)
8813              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8814              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8815             {
8816               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8817               plci->NData[1].PLength = data->Length;
8818               if (data->Flags & 0x10)
8819                 plci->NData[0].P = v120_break_header;
8820               else
8821                 plci->NData[0].P = v120_default_header;
8822               plci->NData[0].PLength = 1 ;
8823               plci->NL.XNum = 2;
8824               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8825             }
8826             else
8827             {
8828               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8829               plci->NData[0].PLength = data->Length;
8830               if (data->Flags & 0x10)
8831                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8832
8833               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8834                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8835
8836               else
8837                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8838             }
8839             plci->NL.X = plci->NData;
8840             plci->NL.ReqCh = a->ncci_ch[ncci];
8841             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8842             plci->data_sent = true;
8843             plci->data_sent_ptr = data->P;
8844             a->request(&plci->NL);
8845           }
8846           else {
8847             cleanup_ncci_data (plci, ncci);
8848           }
8849         }
8850         else if (plci->send_disc == ncci)
8851         {
8852           /* dprintf("N_DISC"); */
8853           plci->NData[0].PLength = 0;
8854           plci->NL.ReqCh = a->ncci_ch[ncci];
8855           plci->NL.Req = plci->nl_req = N_DISC;
8856           a->request(&plci->NL);
8857           plci->command = _DISCONNECT_B3_R;
8858           plci->send_disc = 0;
8859         }
8860       }
8861     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8862     plci->ncci_ring_list = ncci;
8863   }
8864 }
8865
8866 void listen_check(DIVA_CAPI_ADAPTER   * a)
8867 {
8868   word i,j;
8869   PLCI   * plci;
8870   byte activnotifiedcalls = 0;
8871
8872   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8873   if (!remove_started && !a->adapter_disabled)
8874   {
8875     for(i=0;i<a->max_plci;i++)
8876     {
8877       plci = &(a->plci[i]);
8878       if(plci->notifiedcall) activnotifiedcalls++;
8879     }
8880     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8881
8882     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8883       if((j=get_plci(a))) {
8884         a->listen_active++;
8885         plci = &a->plci[j-1];
8886         plci->State = LISTENING;
8887
8888         add_p(plci,OAD,"\x01\xfd");
8889
8890         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8891
8892         add_p(plci,CAI,"\x01\xc0");
8893         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8894         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8895         add_p(plci,SHIFT|6,NULL);
8896         add_p(plci,SIN,"\x02\x00\x00");
8897         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8898         sig_req(plci,ASSIGN,DSIG_ID);
8899         send_req(plci);
8900       }
8901     }
8902   }
8903 }
8904
8905 /*------------------------------------------------------------------*/
8906 /* functions for all parameters sent in INDs                        */
8907 /*------------------------------------------------------------------*/
8908
8909 void IndParse(PLCI   * plci, word * parms_id, byte   ** parms, byte multiIEsize)
8910 {
8911   word ploc;            /* points to current location within packet */
8912   byte w;
8913   byte wlen;
8914   byte codeset,lock;
8915   byte   * in;
8916   word i;
8917   word code;
8918   word mIEindex = 0;
8919   ploc = 0;
8920   codeset = 0;
8921   lock = 0;
8922
8923   in = plci->Sig.RBuffer->P;
8924   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8925   {                            /* element but parms array is larger      */
8926     parms[i] = (byte   *)"";
8927   }
8928   for(i=0; i<multiIEsize; i++)
8929   {
8930     parms[i] = (byte   *)"";
8931   }
8932
8933   while(ploc<plci->Sig.RBuffer->length-1) {
8934
8935         /* read information element id and length                   */
8936     w = in[ploc];
8937
8938     if(w & 0x80) {
8939 /*    w &=0xf0; removed, cannot detect congestion levels */
8940 /*    upper 4 bit masked with w==SHIFT now               */
8941       wlen = 0;
8942     }
8943     else {
8944       wlen = (byte)(in[ploc+1]+1);
8945     }
8946         /* check if length valid (not exceeding end of packet)      */
8947     if((ploc+wlen) > 270) return ;
8948     if(lock & 0x80) lock &=0x7f;
8949     else codeset = lock;
8950
8951     if((w&0xf0)==SHIFT) {
8952       codeset = in[ploc];
8953       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8954       codeset &=7;
8955       lock |=0x80;
8956     }
8957     else {
8958       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8959       else code = w;
8960       code |= (codeset<<8);
8961
8962       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8963
8964       if(i<parms_id[0]+1) {
8965         if(!multiIEsize) { /* with multiIEs use next field index,          */
8966           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8967         }
8968
8969         parms[mIEindex] = &in[ploc+1];
8970         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8971         if(parms_id[i]==OAD
8972         || parms_id[i]==CONN_NR
8973         || parms_id[i]==CAD) {
8974           if(in[ploc+2] &0x80) {
8975             in[ploc+0] = (byte)(in[ploc+1]+1);
8976             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8977             in[ploc+2] = 0x80;
8978             parms[mIEindex] = &in[ploc];
8979           }
8980         }
8981         mIEindex++;       /* effects multiIEs only */
8982       }
8983     }
8984
8985     ploc +=(wlen+1);
8986   }
8987   return ;
8988 }
8989
8990 /*------------------------------------------------------------------*/
8991 /* try to match a cip from received BC and HLC                      */
8992 /*------------------------------------------------------------------*/
8993
8994 byte ie_compare(byte   * ie1, byte * ie2)
8995 {
8996   word i;
8997   if(!ie1 || ! ie2) return false;
8998   if(!ie1[0]) return false;
8999   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9000   return true;
9001 }
9002
9003 word find_cip(DIVA_CAPI_ADAPTER   * a, byte   * bc, byte   * hlc)
9004 {
9005   word i;
9006   word j;
9007
9008   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9009
9010   for(j=16;j<29 &&
9011            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9012   if(j==29) return i;
9013   return j;
9014 }
9015
9016
9017 static byte AddInfo(byte   **add_i,
9018                     byte   **fty_i,
9019                     byte   *esc_chi,
9020                     byte *facility)
9021 {
9022   byte i;
9023   byte j;
9024   byte k;
9025   byte flen;
9026   byte len=0;
9027    /* facility is a nested structure */
9028    /* FTY can be more than once      */
9029
9030   if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9031   {
9032     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9033   }
9034
9035   else
9036   {
9037     add_i[0] = (byte   *)"";
9038   }
9039   if(!fty_i[0][0])
9040   {
9041     add_i[3] = (byte   *)"";
9042   }
9043   else
9044   {    /* facility array found  */
9045     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9046     {
9047       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9048       len += fty_i[i][0];
9049       len += 2;
9050       flen=fty_i[i][0];
9051       facility[j++]=0x1c; /* copy fac IE */
9052       for(k=0;k<=flen;k++,j++)
9053       {
9054         facility[j]=fty_i[i][k];
9055 /*      dbug(1,dprintf("%x ",facility[j])); */
9056       }
9057     }
9058     facility[0] = len;
9059     add_i[3] = facility;
9060   }
9061 /*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9062   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9063   len += 4;                          /* calculate length of all */
9064   return(len);
9065 }
9066
9067 /*------------------------------------------------------------------*/
9068 /* voice and codec features                                         */
9069 /*------------------------------------------------------------------*/
9070
9071 void SetVoiceChannel(PLCI   *plci, byte   *chi, DIVA_CAPI_ADAPTER   * a)
9072 {
9073   byte voice_chi[] = "\x02\x18\x01";
9074   byte channel;
9075
9076   channel = chi[chi[0]]&0x3;
9077   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9078   voice_chi[2] = (channel) ? channel : 1;
9079   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9080   add_p(plci,ESC,voice_chi);                  /* Channel */
9081   sig_req(plci,TEL_CTRL,0);
9082   send_req(plci);
9083   if(a->AdvSignalPLCI)
9084   {
9085     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9086   }
9087 }
9088
9089 void VoiceChannelOff(PLCI   *plci)
9090 {
9091   dbug(1,dprintf("ExtDevOFF"));
9092   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9093   sig_req(plci,TEL_CTRL,0);
9094   send_req(plci);
9095   if(plci->adapter->AdvSignalPLCI)
9096   {
9097     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9098   }
9099 }
9100
9101
9102 word AdvCodecSupport(DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, byte hook_listen)
9103 {
9104   word j;
9105   PLCI   *splci;
9106
9107   /* check if hardware supports handset with hook states (adv.codec) */
9108   /* or if just a on board codec is supported                        */
9109   /* the advanced codec plci is just for internal use                */
9110
9111   /* diva Pro with on-board codec:                                   */
9112   if(a->profile.Global_Options & HANDSET)
9113   {
9114     /* new call, but hook states are already signalled */
9115     if(a->AdvCodecFLAG)
9116     {
9117       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9118       {
9119         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9120         return 0x2001; /* codec in use by another application */
9121       }
9122       if(plci!=0)
9123       {
9124         a->AdvSignalPLCI = plci;
9125         plci->tel=ADV_VOICE;
9126       }
9127       return 0;                      /* adv codec still used */
9128     }
9129     if((j=get_plci(a)))
9130     {
9131       splci = &a->plci[j-1];
9132       splci->tel = CODEC_PERMANENT;
9133       /* hook_listen indicates if a facility_req with handset/hook support */
9134       /* was sent. Otherwise if just a call on an external device was made */
9135       /* the codec will be used but the hook info will be discarded (just  */
9136       /* the external controller is in use                                 */
9137       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9138       else
9139       {
9140         splci->State = ADVANCED_VOICE_NOSIG;
9141         if(plci)
9142         {
9143           plci->spoofed_msg = SPOOFING_REQUIRED;
9144         }
9145                                                /* indicate D-ch connect if  */
9146       }                                        /* codec is connected OK     */
9147       if(plci!=0)
9148       {
9149         a->AdvSignalPLCI = plci;
9150         plci->tel=ADV_VOICE;
9151       }
9152       a->AdvSignalAppl = appl;
9153       a->AdvCodecFLAG = true;
9154       a->AdvCodecPLCI = splci;
9155       add_p(splci,CAI,"\x01\x15");
9156       add_p(splci,LLI,"\x01\x00");
9157       add_p(splci,ESC,"\x02\x18\x00");
9158       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9159       splci->internal_command = PERM_COD_ASSIGN;
9160       dbug(1,dprintf("Codec Assign"));
9161       sig_req(splci,ASSIGN,DSIG_ID);
9162       send_req(splci);
9163     }
9164     else
9165     {
9166       return 0x2001; /* wrong state, no more plcis */
9167     }
9168   }
9169   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9170   {
9171     if(hook_listen) return 0x300B;               /* Facility not supported */
9172                                                  /* no hook with SCOM      */
9173     if(plci!=0) plci->tel = CODEC;
9174     dbug(1,dprintf("S/SCOM codec"));
9175     /* first time we use the scom-s codec we must shut down the internal   */
9176     /* handset application of the card. This can be done by an assign with */
9177     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9178     if(!a->scom_appl_disable){
9179       if((j=get_plci(a))) {
9180         splci = &a->plci[j-1];
9181         add_p(splci,CAI,"\x01\x80");
9182         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9183         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9184         send_req(splci);
9185         a->scom_appl_disable = true;
9186       }
9187       else{
9188         return 0x2001; /* wrong state, no more plcis */
9189       }
9190     }
9191   }
9192   else return 0x300B;               /* Facility not supported */
9193
9194   return 0;
9195 }
9196
9197
9198 void CodecIdCheck(DIVA_CAPI_ADAPTER   *a, PLCI   *plci)
9199 {
9200
9201   dbug(1,dprintf("CodecIdCheck"));
9202
9203   if(a->AdvSignalPLCI == plci)
9204   {
9205     dbug(1,dprintf("PLCI owns codec"));
9206     VoiceChannelOff(a->AdvCodecPLCI);
9207     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9208     {
9209       dbug(1,dprintf("remove temp codec PLCI"));
9210       plci_remove(a->AdvCodecPLCI);
9211       a->AdvCodecFLAG  = 0;
9212       a->AdvCodecPLCI  = NULL;
9213       a->AdvSignalAppl = NULL;
9214     }
9215     a->AdvSignalPLCI = NULL;
9216   }
9217 }
9218
9219 /* -------------------------------------------------------------------
9220     Ask for physical address of card on PCI bus
9221    ------------------------------------------------------------------- */
9222 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9223                                         IDI_SYNC_REQ  * preq) {
9224   a->sdram_bar = 0;
9225   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9226     ENTITY   * e = (ENTITY   *)preq;
9227
9228     e->user[0] = a->Id - 1;
9229     preq->xdi_sdram_bar.info.bar    = 0;
9230     preq->xdi_sdram_bar.Req         = 0;
9231     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9232
9233     (*(a->request))(e);
9234
9235     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9236     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9237   }
9238 }
9239
9240 /* -------------------------------------------------------------------
9241      Ask XDI about extended features
9242    ------------------------------------------------------------------- */
9243 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9244   IDI_SYNC_REQ   * preq;
9245     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9246
9247     char features[4];
9248   preq = (IDI_SYNC_REQ   *)&buffer[0];
9249
9250   if (!diva_xdi_extended_features) {
9251     ENTITY   * e = (ENTITY   *)preq;
9252     diva_xdi_extended_features |= 0x80000000;
9253
9254     e->user[0] = a->Id - 1;
9255     preq->xdi_extended_features.Req = 0;
9256     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9257     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9258     preq->xdi_extended_features.info.features = &features[0];
9259
9260     (*(a->request))(e);
9261
9262     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9263       /*
9264          Check features located in the byte '0'
9265          */
9266       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9267         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9268       }
9269       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9270         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9271         dbug(1,dprintf("XDI provides RxDMA"));
9272       }
9273       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9274         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9275       }
9276       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9277         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9278         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9279       }
9280
9281     }
9282   }
9283
9284   diva_ask_for_xdi_sdram_bar (a, preq);
9285 }
9286
9287 /*------------------------------------------------------------------*/
9288 /* automatic law                                                    */
9289 /*------------------------------------------------------------------*/
9290 /* called from OS specific part after init time to get the Law              */
9291 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9292 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9293 {
9294   word j;
9295   PLCI   *splci;
9296
9297   if(a->automatic_law) {
9298     return;
9299   }
9300   if((j=get_plci(a))) {
9301     diva_get_extended_adapter_features (a);
9302     splci = &a->plci[j-1];
9303     a->automatic_lawPLCI = splci;
9304     a->automatic_law = 1;
9305     add_p(splci,CAI,"\x01\x80");
9306     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9307     splci->internal_command = USELAW_REQ;
9308     splci->command = 0;
9309     splci->number = 0;
9310     sig_req(splci,ASSIGN,DSIG_ID);
9311     send_req(splci);
9312   }
9313 }
9314
9315 /* called from OS specific part if an application sends an Capi20Release */
9316 word CapiRelease(word Id)
9317 {
9318   word i, j, appls_found;
9319   PLCI   *plci;
9320   APPL   *this;
9321   DIVA_CAPI_ADAPTER   *a;
9322
9323   if (!Id)
9324   {
9325     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9326     return (_WRONG_APPL_ID);
9327   }
9328
9329   this = &application[Id-1];               /* get application pointer */
9330
9331   for(i=0,appls_found=0; i<max_appl; i++)
9332   {
9333     if(application[i].Id)       /* an application has been found        */
9334     {
9335       appls_found++;
9336     }
9337   }
9338
9339   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9340   {
9341     a = &adapter[i];
9342     if (a->request)
9343     {
9344       a->Info_Mask[Id-1] = 0;
9345       a->CIP_Mask[Id-1] = 0;
9346       a->Notification_Mask[Id-1] = 0;
9347       a->codec_listen[Id-1] = NULL;
9348       a->requested_options_table[Id-1] = 0;
9349       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9350       {                                      /* with this application   */
9351         plci = &a->plci[j];
9352         if(plci->Id)                         /* if plci owns no application */
9353         {                                    /* it may be not jet connected */
9354           if(plci->State==INC_CON_PENDING
9355           || plci->State==INC_CON_ALERT)
9356           {
9357             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9358             {
9359               clear_c_ind_mask_bit (plci, (word)(Id-1));
9360               if(c_ind_mask_empty (plci))
9361               {
9362                 sig_req(plci,HANGUP,0);
9363                 send_req(plci);
9364                 plci->State = OUTG_DIS_PENDING;
9365               }
9366             }
9367           }
9368           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9369           {
9370             clear_c_ind_mask_bit (plci, (word)(Id-1));
9371             if(c_ind_mask_empty (plci))
9372             {
9373               if(!plci->appl)
9374               {
9375                 plci_remove(plci);
9376                 plci->State = IDLE;
9377               }
9378             }
9379           }
9380           if(plci->appl==this)
9381           {
9382             plci->appl = NULL;
9383             plci_remove(plci);
9384             plci->State = IDLE;
9385           }
9386         }
9387       }
9388       listen_check(a);
9389
9390       if(a->flag_dynamic_l1_down)
9391       {
9392         if(appls_found==1)            /* last application does a capi release */
9393         {
9394           if((j=get_plci(a)))
9395           {
9396             plci = &a->plci[j-1];
9397             plci->command = 0;
9398             add_p(plci,OAD,"\x01\xfd");
9399             add_p(plci,CAI,"\x01\x80");
9400             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9401             add_p(plci,SHIFT|6,NULL);
9402             add_p(plci,SIN,"\x02\x00\x00");
9403             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9404             sig_req(plci,ASSIGN,DSIG_ID);
9405             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9406             sig_req(plci,SIG_CTRL,0);
9407             send_req(plci);
9408           }
9409         }
9410       }
9411       if(a->AdvSignalAppl==this)
9412       {
9413         this->NullCREnable = false;
9414         if (a->AdvCodecPLCI)
9415         {
9416           plci_remove(a->AdvCodecPLCI);
9417           a->AdvCodecPLCI->tel = 0;
9418           a->AdvCodecPLCI->adv_nl = 0;
9419         }
9420         a->AdvSignalAppl = NULL;
9421         a->AdvSignalPLCI = NULL;
9422         a->AdvCodecFLAG = 0;
9423         a->AdvCodecPLCI = NULL;
9424       }
9425     }
9426   }
9427
9428   this->Id = 0;
9429
9430   return GOOD;
9431 }
9432
9433 static word plci_remove_check(PLCI   *plci)
9434 {
9435   if(!plci) return true;
9436   if(!plci->NL.Id && c_ind_mask_empty (plci))
9437   {
9438     if(plci->Sig.Id == 0xff)
9439       plci->Sig.Id = 0;
9440     if(!plci->Sig.Id)
9441     {
9442       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9443       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9444       if (plci->Id)
9445       {
9446         CodecIdCheck(plci->adapter, plci);
9447         clear_b1_config (plci);
9448         ncci_remove (plci, 0, false);
9449         plci_free_msg_in_queue (plci);
9450         channel_flow_control_remove (plci);
9451         plci->Id = 0;
9452         plci->State = IDLE;
9453         plci->channels = 0;
9454         plci->appl = NULL;
9455         plci->notifiedcall = 0;
9456       }
9457       listen_check(plci->adapter);
9458       return true;
9459     }
9460   }
9461   return false;
9462 }
9463
9464
9465 /*------------------------------------------------------------------*/
9466
9467 static byte plci_nl_busy (PLCI   *plci)
9468 {
9469   /* only applicable for non-multiplexed protocols */
9470   return (plci->nl_req
9471     || (plci->ncci_ring_list
9472      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9473      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9474 }
9475
9476
9477 /*------------------------------------------------------------------*/
9478 /* DTMF facilities                                                  */
9479 /*------------------------------------------------------------------*/
9480
9481
9482 static struct
9483 {
9484   byte send_mask;
9485   byte listen_mask;
9486   byte character;
9487   byte code;
9488 } dtmf_digit_map[] =
9489 {
9490   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9491   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9492   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9493   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9494   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9495   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9496   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9497   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9498   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9499   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9500   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9501   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9502   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9503   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9504   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9505   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9506   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9507   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9508   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9509   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9510
9511   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9512   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9513   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9514   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9515   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9516   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9517   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9518   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9519   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9520   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9521   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9522   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9523   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9524   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9525   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9526   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9527   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9528   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9529   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9530   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9531   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9532   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9533   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9534   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9535   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9536   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9537   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9538   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9539   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9540   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9541   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9542   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9543   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9544   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9545   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9546   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9547   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9548   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9549   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9550   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9551   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9552   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9553   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9554   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9555   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9556   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9557   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9558   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9559   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9560   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9561   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9562   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9563
9564 };
9565
9566 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9567
9568
9569 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9570 {
9571   word min_digit_duration, min_gap_duration;
9572
9573   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9574     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9575     (char   *)(FILE_), __LINE__, enable_mask));
9576
9577   if (enable_mask != 0)
9578   {
9579     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9580     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9581     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9582     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9583     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9584     plci->NData[0].PLength = 5;
9585
9586     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9587     plci->NData[0].PLength += 2;
9588     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9589
9590   }
9591   else
9592   {
9593     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9594     plci->NData[0].PLength = 1;
9595
9596     capidtmf_recv_disable (&(plci->capidtmf_state));
9597
9598   }
9599   plci->NData[0].P = plci->internal_req_buffer;
9600   plci->NL.X = plci->NData;
9601   plci->NL.ReqCh = 0;
9602   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9603   plci->adapter->request (&plci->NL);
9604 }
9605
9606
9607 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9608 {
9609   word w, i;
9610
9611   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9612     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9613     (char   *)(FILE_), __LINE__, digit_count));
9614
9615   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9616   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9617   PUT_WORD (&plci->internal_req_buffer[1], w);
9618   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9619   PUT_WORD (&plci->internal_req_buffer[3], w);
9620   for (i = 0; i < digit_count; i++)
9621   {
9622     w = 0;
9623     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9624       && (digit_buffer[i] != dtmf_digit_map[w].character))
9625     {
9626       w++;
9627     }
9628     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9629       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9630   }
9631   plci->NData[0].PLength = 5 + digit_count;
9632   plci->NData[0].P = plci->internal_req_buffer;
9633   plci->NL.X = plci->NData;
9634   plci->NL.ReqCh = 0;
9635   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9636   plci->adapter->request (&plci->NL);
9637 }
9638
9639
9640 static void dtmf_rec_clear_config (PLCI   *plci)
9641 {
9642
9643   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9644     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9645     (char   *)(FILE_), __LINE__));
9646
9647   plci->dtmf_rec_active = 0;
9648   plci->dtmf_rec_pulse_ms = 0;
9649   plci->dtmf_rec_pause_ms = 0;
9650
9651   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9652
9653 }
9654
9655
9656 static void dtmf_send_clear_config (PLCI   *plci)
9657 {
9658
9659   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9660     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9661     (char   *)(FILE_), __LINE__));
9662
9663   plci->dtmf_send_requests = 0;
9664   plci->dtmf_send_pulse_ms = 0;
9665   plci->dtmf_send_pause_ms = 0;
9666 }
9667
9668
9669 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9670 {
9671
9672   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9673     UnMapId (Id), (char   *)(FILE_), __LINE__));
9674
9675   while (plci->dtmf_send_requests != 0)
9676     dtmf_confirmation (Id, plci);
9677 }
9678
9679
9680 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9681 {
9682
9683   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9684     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9685
9686   return (GOOD);
9687 }
9688
9689
9690 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9691 {
9692   word Info;
9693
9694   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9695     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9696
9697   Info = GOOD;
9698   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9699   {
9700     switch (plci->adjust_b_state)
9701     {
9702     case ADJUST_B_RESTORE_DTMF_1:
9703       plci->internal_command = plci->adjust_b_command;
9704       if (plci_nl_busy (plci))
9705       {
9706         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9707         break;
9708       }
9709       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9710       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9711       break;
9712     case ADJUST_B_RESTORE_DTMF_2:
9713       if ((Rc != OK) && (Rc != OK_FC))
9714       {
9715         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9716           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9717         Info = _WRONG_STATE;
9718         break;
9719       }
9720       break;
9721     }
9722   }
9723   return (Info);
9724 }
9725
9726
9727 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9728 {
9729   word internal_command, Info;
9730   byte mask;
9731     byte result[4];
9732
9733   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9734     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9735     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9736     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9737
9738   Info = GOOD;
9739   result[0] = 2;
9740   PUT_WORD (&result[1], DTMF_SUCCESS);
9741   internal_command = plci->internal_command;
9742   plci->internal_command = 0;
9743   mask = 0x01;
9744   switch (plci->dtmf_cmd)
9745   {
9746
9747   case DTMF_LISTEN_TONE_START:
9748     mask <<= 1;
9749   case DTMF_LISTEN_MF_START:
9750     mask <<= 1;
9751
9752   case DTMF_LISTEN_START:
9753     switch (internal_command)
9754     {
9755     default:
9756       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9757         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9758     case DTMF_COMMAND_1:
9759       if (adjust_b_process (Id, plci, Rc) != GOOD)
9760       {
9761         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9762           UnMapId (Id), (char   *)(FILE_), __LINE__));
9763         Info = _FACILITY_NOT_SUPPORTED;
9764         break;
9765       }
9766       if (plci->internal_command)
9767         return;
9768     case DTMF_COMMAND_2:
9769       if (plci_nl_busy (plci))
9770       {
9771         plci->internal_command = DTMF_COMMAND_2;
9772         return;
9773       }
9774       plci->internal_command = DTMF_COMMAND_3;
9775       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9776       return;
9777     case DTMF_COMMAND_3:
9778       if ((Rc != OK) && (Rc != OK_FC))
9779       {
9780         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9781           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9782         Info = _FACILITY_NOT_SUPPORTED;
9783         break;
9784       }
9785
9786       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9787
9788       plci->dtmf_rec_active |= mask;
9789       break;
9790     }
9791     break;
9792
9793
9794   case DTMF_LISTEN_TONE_STOP:
9795     mask <<= 1;
9796   case DTMF_LISTEN_MF_STOP:
9797     mask <<= 1;
9798
9799   case DTMF_LISTEN_STOP:
9800     switch (internal_command)
9801     {
9802     default:
9803       plci->dtmf_rec_active &= ~mask;
9804       if (plci->dtmf_rec_active)
9805         break;
9806 /*
9807     case DTMF_COMMAND_1:
9808       if (plci->dtmf_rec_active)
9809       {
9810         if (plci_nl_busy (plci))
9811         {
9812           plci->internal_command = DTMF_COMMAND_1;
9813           return;
9814         }
9815         plci->dtmf_rec_active &= ~mask;
9816         plci->internal_command = DTMF_COMMAND_2;
9817         dtmf_enable_receiver (plci, false);
9818         return;
9819       }
9820       Rc = OK;
9821     case DTMF_COMMAND_2:
9822       if ((Rc != OK) && (Rc != OK_FC))
9823       {
9824         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9825           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9826         Info = _FACILITY_NOT_SUPPORTED;
9827         break;
9828       }
9829 */
9830       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9831         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9832     case DTMF_COMMAND_3:
9833       if (adjust_b_process (Id, plci, Rc) != GOOD)
9834       {
9835         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9836           UnMapId (Id), (char   *)(FILE_), __LINE__));
9837         Info = _FACILITY_NOT_SUPPORTED;
9838         break;
9839       }
9840       if (plci->internal_command)
9841         return;
9842       break;
9843     }
9844     break;
9845
9846
9847   case DTMF_SEND_TONE:
9848     mask <<= 1;
9849   case DTMF_SEND_MF:
9850     mask <<= 1;
9851
9852   case DTMF_DIGITS_SEND:
9853     switch (internal_command)
9854     {
9855     default:
9856       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9857         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9858         DTMF_COMMAND_1);
9859     case DTMF_COMMAND_1:
9860       if (adjust_b_process (Id, plci, Rc) != GOOD)
9861       {
9862         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9863           UnMapId (Id), (char   *)(FILE_), __LINE__));
9864         Info = _FACILITY_NOT_SUPPORTED;
9865         break;
9866       }
9867       if (plci->internal_command)
9868         return;
9869     case DTMF_COMMAND_2:
9870       if (plci_nl_busy (plci))
9871       {
9872         plci->internal_command = DTMF_COMMAND_2;
9873         return;
9874       }
9875       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9876       plci->internal_command = DTMF_COMMAND_3;
9877       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9878       return;
9879     case DTMF_COMMAND_3:
9880       if ((Rc != OK) && (Rc != OK_FC))
9881       {
9882         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9883           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9884         if (plci->dtmf_send_requests != 0)
9885           (plci->dtmf_send_requests)--;
9886         Info = _FACILITY_NOT_SUPPORTED;
9887         break;
9888       }
9889       return;
9890     }
9891     break;
9892   }
9893   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9894     "wws", Info, SELECTOR_DTMF, result);
9895 }
9896
9897
9898 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9899 {
9900   word Info;
9901   word i, j;
9902   byte mask;
9903     API_PARSE dtmf_parms[5];
9904     byte result[40];
9905
9906   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9907     UnMapId (Id), (char   *)(FILE_), __LINE__));
9908
9909   Info = GOOD;
9910   result[0] = 2;
9911   PUT_WORD (&result[1], DTMF_SUCCESS);
9912   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9913   {
9914     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9915       UnMapId (Id), (char   *)(FILE_), __LINE__));
9916     Info = _FACILITY_NOT_SUPPORTED;
9917   }
9918   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9919   {
9920     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9921       UnMapId (Id), (char   *)(FILE_), __LINE__));
9922     Info = _WRONG_MESSAGE_FORMAT;
9923   }
9924
9925   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9926     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9927   {
9928     if (!((a->requested_options_table[appl->Id-1])
9929         & (1L << PRIVATE_DTMF_TONE)))
9930     {
9931       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9932         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9933       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9934     }
9935     else
9936     {
9937       for (i = 0; i < 32; i++)
9938         result[4 + i] = 0;
9939       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9940       {
9941         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9942         {
9943           if (dtmf_digit_map[i].listen_mask != 0)
9944             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9945         }
9946       }
9947       else
9948       {
9949         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9950         {
9951           if (dtmf_digit_map[i].send_mask != 0)
9952             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9953         }
9954       }
9955       result[0] = 3 + 32;
9956       result[3] = 32;
9957     }
9958   }
9959
9960   else if (plci == NULL)
9961   {
9962     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9963       UnMapId (Id), (char   *)(FILE_), __LINE__));
9964     Info = _WRONG_IDENTIFIER;
9965   }
9966   else
9967   {
9968     if (!plci->State
9969      || !plci->NL.Id || plci->nl_remove_id)
9970     {
9971       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9972         UnMapId (Id), (char   *)(FILE_), __LINE__));
9973       Info = _WRONG_STATE;
9974     }
9975     else
9976     {
9977       plci->command = 0;
9978       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9979       mask = 0x01;
9980       switch (plci->dtmf_cmd)
9981       {
9982
9983       case DTMF_LISTEN_TONE_START:
9984       case DTMF_LISTEN_TONE_STOP:
9985         mask <<= 1;
9986       case DTMF_LISTEN_MF_START:
9987       case DTMF_LISTEN_MF_STOP:
9988         mask <<= 1;
9989         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9990           & (1L << PRIVATE_DTMF_TONE)))
9991         {
9992           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9993             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9994           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9995           break;
9996         }
9997
9998       case DTMF_LISTEN_START:
9999       case DTMF_LISTEN_STOP:
10000         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10001          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10002         {
10003           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10004             UnMapId (Id), (char   *)(FILE_), __LINE__));
10005           Info = _FACILITY_NOT_SUPPORTED;
10006           break;
10007         }
10008         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10009         {
10010           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10011           {
10012             plci->dtmf_rec_pulse_ms = 0;
10013             plci->dtmf_rec_pause_ms = 0;
10014           }
10015           else
10016           {
10017             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10018             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10019           }
10020         }
10021         start_internal_command (Id, plci, dtmf_command);
10022         return (false);
10023
10024
10025       case DTMF_SEND_TONE:
10026         mask <<= 1;
10027       case DTMF_SEND_MF:
10028         mask <<= 1;
10029         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10030           & (1L << PRIVATE_DTMF_TONE)))
10031         {
10032           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10033             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10034           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10035           break;
10036         }
10037
10038       case DTMF_DIGITS_SEND:
10039         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10040         {
10041           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10042             UnMapId (Id), (char   *)(FILE_), __LINE__));
10043           Info = _WRONG_MESSAGE_FORMAT;
10044           break;
10045         }
10046         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10047         {
10048           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10049           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10050         }
10051         i = 0;
10052         j = 0;
10053         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10054         {
10055           j = 0;
10056           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10057             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10058              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10059           {
10060             j++;
10061           }
10062           i++;
10063         }
10064         if (j == DTMF_DIGIT_MAP_ENTRIES)
10065         {
10066           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10067             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10068           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10069           break;
10070         }
10071         if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10072         {
10073           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10074             UnMapId (Id), (char   *)(FILE_), __LINE__));
10075           Info = _WRONG_STATE;
10076           break;
10077         }
10078         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10079         start_internal_command (Id, plci, dtmf_command);
10080         return (false);
10081
10082       default:
10083         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10084           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10085         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10086       }
10087     }
10088   }
10089   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10090     "wws", Info, SELECTOR_DTMF, result);
10091   return (false);
10092 }
10093
10094
10095 static void dtmf_confirmation (dword Id, PLCI   *plci)
10096 {
10097   word Info;
10098   word i;
10099     byte result[4];
10100
10101   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10102     UnMapId (Id), (char   *)(FILE_), __LINE__));
10103
10104   Info = GOOD;
10105   result[0] = 2;
10106   PUT_WORD (&result[1], DTMF_SUCCESS);
10107   if (plci->dtmf_send_requests != 0)
10108   {
10109     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10110       "wws", GOOD, SELECTOR_DTMF, result);
10111     (plci->dtmf_send_requests)--;
10112     for (i = 0; i < plci->dtmf_send_requests; i++)
10113       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10114   }
10115 }
10116
10117
10118 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10119 {
10120   word i, j, n;
10121
10122   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10123     UnMapId (Id), (char   *)(FILE_), __LINE__));
10124
10125   n = 0;
10126   for (i = 1; i < length; i++)
10127   {
10128     j = 0;
10129     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10130       && ((msg[i] != dtmf_digit_map[j].code)
10131        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10132     {
10133       j++;
10134     }
10135     if (j < DTMF_DIGIT_MAP_ENTRIES)
10136     {
10137
10138       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10139        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10140        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10141       {
10142         if (n + 1 == i)
10143         {
10144           for (i = length; i > n + 1; i--)
10145             msg[i] = msg[i - 1];
10146           length++;
10147           i++;
10148         }
10149         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10150       }
10151       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10152
10153       msg[++n] = dtmf_digit_map[j].character;
10154     }
10155   }
10156   if (n != 0)
10157   {
10158     msg[0] = (byte) n;
10159     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10160   }
10161 }
10162
10163
10164 /*------------------------------------------------------------------*/
10165 /* DTMF parameters                                                  */
10166 /*------------------------------------------------------------------*/
10167
10168 static void dtmf_parameter_write (PLCI   *plci)
10169 {
10170   word i;
10171     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10172
10173   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10174     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10175     (char   *)(FILE_), __LINE__));
10176
10177   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10178   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10179   for (i = 0; i < plci->dtmf_parameter_length; i++)
10180     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10181   add_p (plci, FTY, parameter_buffer);
10182   sig_req (plci, TEL_CTRL, 0);
10183   send_req (plci);
10184 }
10185
10186
10187 static void dtmf_parameter_clear_config (PLCI   *plci)
10188 {
10189
10190   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10191     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10192     (char   *)(FILE_), __LINE__));
10193
10194   plci->dtmf_parameter_length = 0;
10195 }
10196
10197
10198 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10199 {
10200
10201   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10202     UnMapId (Id), (char   *)(FILE_), __LINE__));
10203
10204 }
10205
10206
10207 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10208 {
10209
10210   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10211     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10212
10213   return (GOOD);
10214 }
10215
10216
10217 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10218 {
10219   word Info;
10220
10221   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10222     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10223
10224   Info = GOOD;
10225   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10226    && (plci->dtmf_parameter_length != 0))
10227   {
10228     switch (plci->adjust_b_state)
10229     {
10230     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10231       plci->internal_command = plci->adjust_b_command;
10232       if (plci->sig_req)
10233       {
10234         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10235         break;
10236       }
10237       dtmf_parameter_write (plci);
10238       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10239       break;
10240     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10241       if ((Rc != OK) && (Rc != OK_FC))
10242       {
10243         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10244           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10245         Info = _WRONG_STATE;
10246         break;
10247       }
10248       break;
10249     }
10250   }
10251   return (Info);
10252 }
10253
10254
10255 /*------------------------------------------------------------------*/
10256 /* Line interconnect facilities                                     */
10257 /*------------------------------------------------------------------*/
10258
10259
10260 LI_CONFIG   *li_config_table;
10261 word li_total_channels;
10262
10263
10264 /*------------------------------------------------------------------*/
10265 /* translate a CHI information element to a channel number          */
10266 /* returns 0xff - any channel                                       */
10267 /*         0xfe - chi wrong coding                                  */
10268 /*         0xfd - D-channel                                         */
10269 /*         0x00 - no channel                                        */
10270 /*         else channel number / PRI: timeslot                      */
10271 /* if channels is provided we accept more than one channel.         */
10272 /*------------------------------------------------------------------*/
10273
10274 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10275 {
10276   int p;
10277   int i;
10278   dword map;
10279   byte excl;
10280   byte ofs;
10281   byte ch;
10282
10283   if (pchannelmap) *pchannelmap = 0;
10284   if(!chi[0]) return 0xff;
10285   excl = 0;
10286
10287   if(chi[1] & 0x20) {
10288     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10289     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10290     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10291     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10292     if(chi[1] &0x08) excl = 0x40;
10293
10294         /* int. id present */
10295     if(chi[1] &0x40) {
10296       p=i+1;
10297       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10298       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10299     }
10300
10301         /* coding standard, Number/Map, Channel Type */
10302     p=i+1;
10303     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10304     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10305     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10306
10307         /* Number/Map */
10308     if(chi[p] &0x10) {
10309
10310         /* map */
10311       if((chi[0]-p)==4) ofs = 0;
10312       else if((chi[0]-p)==3) ofs = 1;
10313       else return 0xfe;
10314       ch = 0;
10315       map = 0;
10316       for(i=0; i<4 && p<chi[0]; i++) {
10317         p++;
10318         ch += 8;
10319         map <<= 8;
10320         if(chi[p]) {
10321           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10322           map |= chi[p];
10323         }
10324       }
10325       ch += ofs;
10326       map <<= ofs;
10327     }
10328     else {
10329
10330         /* number */
10331       p=i+1;
10332       ch = chi[p] &0x3f;
10333       if(pchannelmap) {
10334         if((byte)(chi[0]-p)>30) return 0xfe;
10335         map = 0;
10336         for(i=p; i<=chi[0]; i++) {
10337           if ((chi[i] &0x7f) > 31) return 0xfe;
10338           map |= (1L << (chi[i] &0x7f));
10339         }
10340       }
10341       else {
10342         if(p!=chi[0]) return 0xfe;
10343         if (ch > 31) return 0xfe;
10344         map = (1L << ch);
10345       }
10346       if(chi[p] &0x40) return 0xfe;
10347     }
10348     if (pchannelmap) *pchannelmap = map;
10349     else if (map != ((dword)(1L << ch))) return 0xfe;
10350     return (byte)(excl | ch);
10351   }
10352   else {  /* not PRI */
10353     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10354     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10355     if(chi[1] &0x08) excl = 0x40;
10356
10357     switch(chi[1] |0x98) {
10358     case 0x98: return 0;
10359     case 0x99:
10360       if (pchannelmap) *pchannelmap = 2;
10361       return excl |1;
10362     case 0x9a:
10363       if (pchannelmap) *pchannelmap = 4;
10364       return excl |2;
10365     case 0x9b: return 0xff;
10366     case 0x9c: return 0xfd; /* d-ch */
10367     default: return 0xfe;
10368     }
10369   }
10370 }
10371
10372
10373 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10374 {
10375   DIVA_CAPI_ADAPTER   *a;
10376   PLCI   *splci;
10377   byte old_id;
10378
10379   a = plci->adapter;
10380   old_id = plci->li_bchannel_id;
10381   if (a->li_pri)
10382   {
10383     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10384       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10385     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10386     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10387       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10388   }
10389   else
10390   {
10391     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10392     {
10393       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10394         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10395       plci->li_bchannel_id = bchannel_id & 0x03;
10396       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10397       {
10398         splci = a->AdvSignalPLCI;
10399         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10400         {
10401           if ((splci->li_bchannel_id != 0)
10402            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10403           {
10404             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10405           }
10406           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10407           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10408           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10409             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10410             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10411         }
10412       }
10413       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10414         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10415     }
10416   }
10417   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10418    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10419   {
10420     mixer_clear_config (plci);
10421   }
10422   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10423     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10424     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10425 }
10426
10427
10428 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10429 {
10430   DIVA_CAPI_ADAPTER   *a;
10431   PLCI   *splci;
10432   byte ch, old_id;
10433
10434   a = plci->adapter;
10435   old_id = plci->li_bchannel_id;
10436   ch = chi_to_channel (chi, NULL);
10437   if (!(ch & 0x80))
10438   {
10439     if (a->li_pri)
10440     {
10441       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10442         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10443       plci->li_bchannel_id = (ch & 0x1f) + 1;
10444       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10445         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10446     }
10447     else
10448     {
10449       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10450       {
10451         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10452           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10453         plci->li_bchannel_id = ch & 0x1f;
10454         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10455         {
10456           splci = a->AdvSignalPLCI;
10457           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10458           {
10459             if ((splci->li_bchannel_id != 0)
10460              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10461             {
10462               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10463             }
10464             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10465             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10466             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10467               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10468               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10469           }
10470         }
10471         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10472           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10473       }
10474     }
10475   }
10476   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10477    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10478   {
10479     mixer_clear_config (plci);
10480   }
10481   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10482     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10483     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10484 }
10485
10486
10487 #define MIXER_MAX_DUMP_CHANNELS 34
10488
10489 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10490 {
10491 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10492   word n, i, j;
10493   char *p;
10494     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10495
10496   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10497     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10498
10499   for (i = 0; i < li_total_channels; i++)
10500   {
10501     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10502     if (li_config_table[i].chflags != 0)
10503       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10504     else
10505     {
10506       for (j = 0; j < li_total_channels; j++)
10507       {
10508         if (((li_config_table[i].flag_table[j]) != 0)
10509          || ((li_config_table[j].flag_table[i]) != 0))
10510         {
10511           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10512         }
10513         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10514          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10515         {
10516           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10517         }
10518       }
10519     }
10520   }
10521   for (i = 0; i < li_total_channels; i++)
10522   {
10523     for (j = 0; j < li_total_channels; j++)
10524     {
10525       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10526       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10527         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10528     }
10529   }
10530   for (n = 0; n < li_total_channels; n++)
10531   {
10532     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10533     {
10534       for (i = 0; i < li_total_channels; i++)
10535       {
10536         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10537         {
10538           for (j = 0; j < li_total_channels; j++)
10539           {
10540             li_config_table[i].coef_table[j] |=
10541               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10542           }
10543         }
10544       }
10545     }
10546   }
10547   for (i = 0; i < li_total_channels; i++)
10548   {
10549     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10550     {
10551       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10552       for (j = 0; j < li_total_channels; j++)
10553       {
10554         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10555           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10556       }
10557       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10558         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10559     }
10560   }
10561   for (i = 0; i < li_total_channels; i++)
10562   {
10563     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10564     {
10565       for (j = 0; j < li_total_channels; j++)
10566       {
10567         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10568           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10569         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10570           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10571         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10572           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10573         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10574           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10575       }
10576       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10577       {
10578         for (j = 0; j < li_total_channels; j++)
10579         {
10580           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10581           {
10582             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10583             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10584               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10585           }
10586         }
10587       }
10588       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10589       {
10590         for (j = 0; j < li_total_channels; j++)
10591         {
10592           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10593             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10594         }
10595       }
10596       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10597       {
10598         for (j = 0; j < li_total_channels; j++)
10599         {
10600           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10601           {
10602             for (n = 0; n < li_total_channels; n++)
10603             {
10604               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10605               {
10606                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10607                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10608                 {
10609                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10610                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10611                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10612                 }
10613                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10614                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10615               }
10616             }
10617           }
10618         }
10619       }
10620     }
10621   }
10622   for (i = 0; i < li_total_channels; i++)
10623   {
10624     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10625     {
10626       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10627         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10628       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10629         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10630       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10631         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10632       for (j = 0; j < li_total_channels; j++)
10633       {
10634         if ((li_config_table[i].flag_table[j] &
10635           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10636          || (li_config_table[j].flag_table[i] &
10637           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10638         {
10639           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10640         }
10641         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10642           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10643         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10644           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10645       }
10646       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10647       {
10648         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10649         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10650       }
10651     }
10652   }
10653   for (i = 0; i < li_total_channels; i++)
10654   {
10655     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10656     {
10657       j = 0;
10658       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10659         j++;
10660       if (j < li_total_channels)
10661       {
10662         for (j = 0; j < li_total_channels; j++)
10663         {
10664           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10665           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10666             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10667         }
10668       }
10669     }
10670   }
10671   n = li_total_channels;
10672   if (n > MIXER_MAX_DUMP_CHANNELS)
10673     n = MIXER_MAX_DUMP_CHANNELS;
10674   p = hex_line;
10675   for (j = 0; j < n; j++)
10676   {
10677     if ((j & 0x7) == 0)
10678       *(p++) = ' ';
10679     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10680     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10681   }
10682   *p = '\0';
10683   dbug (1, dprintf ("[%06lx] CURRENT %s",
10684     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10685   p = hex_line;
10686   for (j = 0; j < n; j++)
10687   {
10688     if ((j & 0x7) == 0)
10689       *(p++) = ' ';
10690     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10691     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10692   }
10693   *p = '\0';
10694   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10695     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10696   p = hex_line;
10697   for (j = 0; j < n; j++)
10698   {
10699     if ((j & 0x7) == 0)
10700       *(p++) = ' ';
10701     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10702     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10703   }
10704   *p = '\0';
10705   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10706     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10707   for (i = 0; i < n; i++)
10708   {
10709     p = hex_line;
10710     for (j = 0; j < n; j++)
10711     {
10712       if ((j & 0x7) == 0)
10713         *(p++) = ' ';
10714       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10715       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10716     }
10717     *p = '\0';
10718     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10719       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10720   }
10721   for (i = 0; i < n; i++)
10722   {
10723     p = hex_line;
10724     for (j = 0; j < n; j++)
10725     {
10726       if ((j & 0x7) == 0)
10727         *(p++) = ' ';
10728       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10729       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10730     }
10731     *p = '\0';
10732     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10733       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10734   }
10735 }
10736
10737
10738 static struct
10739 {
10740   byte mask;
10741   byte line_flags;
10742 } mixer_write_prog_pri[] =
10743 {
10744   { LI_COEF_CH_CH, 0 },
10745   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10746   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10747   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10748 };
10749
10750 static struct
10751 {
10752   byte from_ch;
10753   byte to_ch;
10754   byte mask;
10755   byte xconnect_override;
10756 } mixer_write_prog_bri[] =
10757 {
10758   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10759   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10760   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10761   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10762   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10763   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10764   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10765   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10766   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10767   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10768   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10769   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10770   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10771   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10772   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10773   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10774   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10775   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10776   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10777   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10778   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10779   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10780   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10781   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10782   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10783   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10784   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10785   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10786   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10787   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10788   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10789   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10790   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10791   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10792   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10793   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10794 };
10795
10796 static byte mixer_swapped_index_bri[] =
10797 {
10798   18,  /* B      to B      */
10799   19,  /* Alt B  to B      */
10800   20,  /* PC     to B      */
10801   21,  /* Alt PC to B      */
10802   22,  /* IC     to B      */
10803   23,  /* Alt IC to B      */
10804   24,  /* B      to PC     */
10805   25,  /* Alt B  to PC     */
10806   26,  /* PC     to PC     */
10807   27,  /* Alt PC to PC     */
10808   28,  /* IC     to PC     */
10809   29,  /* Alt IC to PC     */
10810   30,  /* B      to IC     */
10811   31,  /* Alt B  to IC     */
10812   32,  /* PC     to IC     */
10813   33,  /* Alt PC to IC     */
10814   34,  /* IC     to IC     */
10815   35,  /* Alt IC to IC     */
10816   0,   /* Alt B  to Alt B  */
10817   1,   /* B      to Alt B  */
10818   2,   /* Alt PC to Alt B  */
10819   3,   /* PC     to Alt B  */
10820   4,   /* Alt IC to Alt B  */
10821   5,   /* IC     to Alt B  */
10822   6,   /* Alt B  to Alt PC */
10823   7,   /* B      to Alt PC */
10824   8,   /* Alt PC to Alt PC */
10825   9,   /* PC     to Alt PC */
10826   10,  /* Alt IC to Alt PC */
10827   11,  /* IC     to Alt PC */
10828   12,  /* Alt B  to Alt IC */
10829   13,  /* B      to Alt IC */
10830   14,  /* Alt PC to Alt IC */
10831   15,  /* PC     to Alt IC */
10832   16,  /* Alt IC to Alt IC */
10833   17   /* IC     to Alt IC */
10834 };
10835
10836 static struct
10837 {
10838   byte mask;
10839   byte from_pc;
10840   byte to_pc;
10841 } xconnect_write_prog[] =
10842 {
10843   { LI_COEF_CH_CH, false, false },
10844   { LI_COEF_CH_PC, false, true },
10845   { LI_COEF_PC_CH, true, false },
10846   { LI_COEF_PC_PC, true, true }
10847 };
10848
10849
10850 static void xconnect_query_addresses (PLCI   *plci)
10851 {
10852   DIVA_CAPI_ADAPTER   *a;
10853   word w, ch;
10854   byte   *p;
10855
10856   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10857     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10858     (char   *)(FILE_), __LINE__));
10859
10860   a = plci->adapter;
10861   if (a->li_pri && ((plci->li_bchannel_id == 0)
10862    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10863   {
10864     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10865       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10866       (char   *)(FILE_), __LINE__));
10867     return;
10868   }
10869   p = plci->internal_req_buffer;
10870   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10871   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10872   w = ch;
10873   *(p++) = (byte) w;
10874   *(p++) = (byte)(w >> 8);
10875   w = ch | XCONNECT_CHANNEL_PORT_PC;
10876   *(p++) = (byte) w;
10877   *(p++) = (byte)(w >> 8);
10878   plci->NData[0].P = plci->internal_req_buffer;
10879   plci->NData[0].PLength = p - plci->internal_req_buffer;
10880   plci->NL.X = plci->NData;
10881   plci->NL.ReqCh = 0;
10882   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10883   plci->adapter->request (&plci->NL);
10884 }
10885
10886
10887 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10888 {
10889
10890   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10891     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10892     (char   *)(FILE_), __LINE__, internal_command));
10893
10894   plci->li_write_command = internal_command;
10895   plci->li_write_channel = 0;
10896 }
10897
10898
10899 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10900 {
10901   DIVA_CAPI_ADAPTER   *a;
10902   word w, n, i, j, r, s, to_ch;
10903   dword d;
10904   byte   *p;
10905   struct xconnect_transfer_address_s   *transfer_address;
10906   byte ch_map[MIXER_CHANNELS_BRI];
10907
10908   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10909     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10910
10911   a = plci->adapter;
10912   if ((plci->li_bchannel_id == 0)
10913    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10914   {
10915     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10916       UnMapId (Id), (char   *)(FILE_), __LINE__));
10917     return (true);
10918   }
10919   i = a->li_base + (plci->li_bchannel_id - 1);
10920   j = plci->li_write_channel;
10921   p = plci->internal_req_buffer;
10922   if (j != 0)
10923   {
10924     if ((Rc != OK) && (Rc != OK_FC))
10925     {
10926       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10927         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10928       return (false);
10929     }
10930   }
10931   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10932   {
10933     r = 0;
10934     s = 0;
10935     if (j < li_total_channels)
10936     {
10937       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10938       {
10939         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10940             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10941           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10942             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10943       }
10944       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10945       while ((j < li_total_channels)
10946         && ((r == 0)
10947          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10948          || (!li_config_table[j].adapter->li_pri
10949           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10950          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10951            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10952           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10953            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10954          || ((li_config_table[j].adapter->li_base != a->li_base)
10955           && !(r & s &
10956             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10957               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10958             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10959               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10960       {
10961         j++;
10962         if (j < li_total_channels)
10963           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964       }
10965     }
10966     if (j < li_total_channels)
10967     {
10968       plci->internal_command = plci->li_write_command;
10969       if (plci_nl_busy (plci))
10970         return (true);
10971       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10972       *(p++) = UDATA_REQUEST_XCONNECT_TO;
10973       do
10974       {
10975         if (li_config_table[j].adapter->li_base != a->li_base)
10976         {
10977           r &= s &
10978             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10979               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10980             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10981               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10982         }
10983         n = 0;
10984         do
10985         {
10986           if (r & xconnect_write_prog[n].mask)
10987           {
10988             if (xconnect_write_prog[n].from_pc)
10989               transfer_address = &(li_config_table[j].send_pc);
10990             else
10991               transfer_address = &(li_config_table[j].send_b);
10992             d = transfer_address->card_address.low;
10993             *(p++) = (byte) d;
10994             *(p++) = (byte)(d >> 8);
10995             *(p++) = (byte)(d >> 16);
10996             *(p++) = (byte)(d >> 24);
10997             d = transfer_address->card_address.high;
10998             *(p++) = (byte) d;
10999             *(p++) = (byte)(d >> 8);
11000             *(p++) = (byte)(d >> 16);
11001             *(p++) = (byte)(d >> 24);
11002             d = transfer_address->offset;
11003             *(p++) = (byte) d;
11004             *(p++) = (byte)(d >> 8);
11005             *(p++) = (byte)(d >> 16);
11006             *(p++) = (byte)(d >> 24);
11007             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11008             *(p++) = (byte) w;
11009             *(p++) = (byte)(w >> 8);
11010             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11011               (li_config_table[i].adapter->u_law ?
11012                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11013                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11014             *(p++) = (byte) w;
11015             *(p++) = (byte) 0;
11016             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11017           }
11018           n++;
11019         } while ((n < ARRAY_SIZE(xconnect_write_prog))
11020           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11021         if (n == ARRAY_SIZE(xconnect_write_prog))
11022         {
11023           do
11024           {
11025             j++;
11026             if (j < li_total_channels)
11027               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11028           } while ((j < li_total_channels)
11029             && ((r == 0)
11030              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11031              || (!li_config_table[j].adapter->li_pri
11032               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11033              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11034                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11035               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11036                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11037              || ((li_config_table[j].adapter->li_base != a->li_base)
11038               && !(r & s &
11039                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11040                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11041                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11042                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11043         }
11044       } while ((j < li_total_channels)
11045         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11046     }
11047     else if (j == li_total_channels)
11048     {
11049       plci->internal_command = plci->li_write_command;
11050       if (plci_nl_busy (plci))
11051         return (true);
11052       if (a->li_pri)
11053       {
11054         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11055         w = 0;
11056         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11057           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11058         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11059           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11060         *(p++) = (byte) w;
11061         *(p++) = (byte)(w >> 8);
11062       }
11063       else
11064       {
11065         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11066         w = 0;
11067         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11068          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11069         {
11070           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11071         }
11072         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11073           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11074         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11075           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11076         *(p++) = (byte) w;
11077         *(p++) = (byte)(w >> 8);
11078         for (j = 0; j < sizeof(ch_map); j += 2)
11079         {
11080           if (plci->li_bchannel_id == 2)
11081           {
11082             ch_map[j] = (byte)(j+1);
11083             ch_map[j+1] = (byte) j;
11084           }
11085           else
11086           {
11087             ch_map[j] = (byte) j;
11088             ch_map[j+1] = (byte)(j+1);
11089           }
11090         }
11091         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11092         {
11093           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11094           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11095           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11096           {
11097             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11098               mixer_write_prog_bri[n].xconnect_override :
11099               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11100             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11101             {
11102               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11103               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11104             }
11105           }
11106           else
11107           {
11108             *p = 0x00;
11109             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11110             {
11111               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11112               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11113                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11114             }
11115           }
11116           p++;
11117         }
11118       }
11119       j = li_total_channels + 1;
11120     }
11121   }
11122   else
11123   {
11124     if (j <= li_total_channels)
11125     {
11126       plci->internal_command = plci->li_write_command;
11127       if (plci_nl_busy (plci))
11128         return (true);
11129       if (j < a->li_base)
11130         j = a->li_base;
11131       if (a->li_pri)
11132       {
11133         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11134         w = 0;
11135         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11136           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11137         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11138           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11139         *(p++) = (byte) w;
11140         *(p++) = (byte)(w >> 8);
11141         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11142         {
11143           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11144           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11145           {
11146             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11147             if (w & mixer_write_prog_pri[n].mask)
11148             {
11149               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11150               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11151             }
11152             else
11153               *(p++) = 0x00;
11154           }
11155           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11156           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11157           {
11158             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11159             if (w & mixer_write_prog_pri[n].mask)
11160             {
11161               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11162               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11163             }
11164             else
11165               *(p++) = 0x00;
11166           }
11167         }
11168       }
11169       else
11170       {
11171         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11172         w = 0;
11173         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11174          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11175         {
11176           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11177         }
11178         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11179           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11180         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11181           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11182         *(p++) = (byte) w;
11183         *(p++) = (byte)(w >> 8);
11184         for (j = 0; j < sizeof(ch_map); j += 2)
11185         {
11186           if (plci->li_bchannel_id == 2)
11187           {
11188             ch_map[j] = (byte)(j+1);
11189             ch_map[j+1] = (byte) j;
11190           }
11191           else
11192           {
11193             ch_map[j] = (byte) j;
11194             ch_map[j+1] = (byte)(j+1);
11195           }
11196         }
11197         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11198         {
11199           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11200           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11201           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11202           {
11203             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11204             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11205             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11206           }
11207           else
11208           {
11209             *p = 0x00;
11210             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11211             {
11212               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11213               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11214                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11215             }
11216           }
11217           p++;
11218         }
11219       }
11220       j = li_total_channels + 1;
11221     }
11222   }
11223   plci->li_write_channel = j;
11224   if (p != plci->internal_req_buffer)
11225   {
11226     plci->NData[0].P = plci->internal_req_buffer;
11227     plci->NData[0].PLength = p - plci->internal_req_buffer;
11228     plci->NL.X = plci->NData;
11229     plci->NL.ReqCh = 0;
11230     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11231     plci->adapter->request (&plci->NL);
11232   }
11233   return (true);
11234 }
11235
11236
11237 static void mixer_notify_update (PLCI   *plci, byte others)
11238 {
11239   DIVA_CAPI_ADAPTER   *a;
11240   word i, w;
11241   PLCI   *notify_plci;
11242     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11243
11244   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11245     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11246     (char   *)(FILE_), __LINE__, others));
11247
11248   a = plci->adapter;
11249   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11250   {
11251     if (others)
11252       plci->li_notify_update = true;
11253     i = 0;
11254     do
11255     {
11256       notify_plci = NULL;
11257       if (others)
11258       {
11259         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11260           i++;
11261         if (i < li_total_channels)
11262           notify_plci = li_config_table[i++].plci;
11263       }
11264       else
11265       {
11266         if ((plci->li_bchannel_id != 0)
11267          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11268         {
11269           notify_plci = plci;
11270         }
11271       }
11272       if ((notify_plci != NULL)
11273        && !notify_plci->li_notify_update
11274        && (notify_plci->appl != NULL)
11275        && (notify_plci->State)
11276        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11277       {
11278         notify_plci->li_notify_update = true;
11279         ((CAPI_MSG *) msg)->header.length = 18;
11280         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11281         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11282         ((CAPI_MSG *) msg)->header.number = 0;
11283         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11284         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11285         ((CAPI_MSG *) msg)->header.ncci = 0;
11286         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11287         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11288         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11289         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11290         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11291         if (w != _QUEUE_FULL)
11292         {
11293           if (w != 0)
11294           {
11295             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11296               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11297               (char   *)(FILE_), __LINE__,
11298               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11299           }
11300           notify_plci->li_notify_update = false;
11301         }
11302       }
11303     } while (others && (notify_plci != NULL));
11304     if (others)
11305       plci->li_notify_update = false;
11306   }
11307 }
11308
11309
11310 static void mixer_clear_config (PLCI   *plci)
11311 {
11312   DIVA_CAPI_ADAPTER   *a;
11313   word i, j;
11314
11315   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11316     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11317     (char   *)(FILE_), __LINE__));
11318
11319   plci->li_notify_update = false;
11320   plci->li_plci_b_write_pos = 0;
11321   plci->li_plci_b_read_pos = 0;
11322   plci->li_plci_b_req_pos = 0;
11323   a = plci->adapter;
11324   if ((plci->li_bchannel_id != 0)
11325    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11326   {
11327     i = a->li_base + (plci->li_bchannel_id - 1);
11328     li_config_table[i].curchnl = 0;
11329     li_config_table[i].channel = 0;
11330     li_config_table[i].chflags = 0;
11331     for (j = 0; j < li_total_channels; j++)
11332     {
11333       li_config_table[j].flag_table[i] = 0;
11334       li_config_table[i].flag_table[j] = 0;
11335       li_config_table[i].coef_table[j] = 0;
11336       li_config_table[j].coef_table[i] = 0;
11337     }
11338     if (!a->li_pri)
11339     {
11340       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11341       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11342       {
11343         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11344         li_config_table[i].curchnl = 0;
11345         li_config_table[i].channel = 0;
11346         li_config_table[i].chflags = 0;
11347         for (j = 0; j < li_total_channels; j++)
11348         {
11349           li_config_table[i].flag_table[j] = 0;
11350           li_config_table[j].flag_table[i] = 0;
11351           li_config_table[i].coef_table[j] = 0;
11352           li_config_table[j].coef_table[i] = 0;
11353         }
11354         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11355         {
11356           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11357           li_config_table[i].curchnl = 0;
11358           li_config_table[i].channel = 0;
11359           li_config_table[i].chflags = 0;
11360           for (j = 0; j < li_total_channels; j++)
11361           {
11362             li_config_table[i].flag_table[j] = 0;
11363             li_config_table[j].flag_table[i] = 0;
11364             li_config_table[i].coef_table[j] = 0;
11365             li_config_table[j].coef_table[i] = 0;
11366           }
11367         }
11368       }
11369     }
11370   }
11371 }
11372
11373
11374 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11375 {
11376
11377   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11378     UnMapId (Id), (char   *)(FILE_), __LINE__));
11379
11380   do
11381   {
11382     mixer_indication_coefs_set (Id, plci);
11383   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11384 }
11385
11386
11387 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11388 {
11389   DIVA_CAPI_ADAPTER   *a;
11390   word i, j;
11391
11392   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11393     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11394
11395   a = plci->adapter;
11396   if ((plci->li_bchannel_id != 0)
11397    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11398   {
11399     i = a->li_base + (plci->li_bchannel_id - 1);
11400     for (j = 0; j < li_total_channels; j++)
11401     {
11402       li_config_table[i].coef_table[j] &= 0xf;
11403       li_config_table[j].coef_table[i] &= 0xf;
11404     }
11405     if (!a->li_pri)
11406       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11407   }
11408   return (GOOD);
11409 }
11410
11411
11412 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11413 {
11414   DIVA_CAPI_ADAPTER   *a;
11415   word Info;
11416
11417   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11418     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11419
11420   Info = GOOD;
11421   a = plci->adapter;
11422   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11423    && (plci->li_bchannel_id != 0)
11424    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11425   {
11426     switch (plci->adjust_b_state)
11427     {
11428     case ADJUST_B_RESTORE_MIXER_1:
11429       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11430       {
11431         plci->internal_command = plci->adjust_b_command;
11432         if (plci_nl_busy (plci))
11433         {
11434           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11435           break;
11436         }
11437         xconnect_query_addresses (plci);
11438         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11439         break;
11440       }
11441       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11442       Rc = OK;
11443     case ADJUST_B_RESTORE_MIXER_2:
11444     case ADJUST_B_RESTORE_MIXER_3:
11445     case ADJUST_B_RESTORE_MIXER_4:
11446       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11447       {
11448         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11449           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11450         Info = _WRONG_STATE;
11451         break;
11452       }
11453       if (Rc == OK)
11454       {
11455         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11456           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11457         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11458           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11459       }
11460       else if (Rc == 0)
11461       {
11462         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11463           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11464         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11465           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11466       }
11467       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11468       {
11469         plci->internal_command = plci->adjust_b_command;
11470         break;
11471       }
11472     case ADJUST_B_RESTORE_MIXER_5:
11473       xconnect_write_coefs (plci, plci->adjust_b_command);
11474       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11475       Rc = OK;
11476     case ADJUST_B_RESTORE_MIXER_6:
11477       if (!xconnect_write_coefs_process (Id, plci, Rc))
11478       {
11479         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11480           UnMapId (Id), (char   *)(FILE_), __LINE__));
11481         Info = _FACILITY_NOT_SUPPORTED;
11482         break;
11483       }
11484       if (plci->internal_command)
11485         break;
11486       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11487     case ADJUST_B_RESTORE_MIXER_7:
11488       break;
11489     }
11490   }
11491   return (Info);
11492 }
11493
11494
11495 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11496 {
11497   DIVA_CAPI_ADAPTER   *a;
11498   word i, internal_command, Info;
11499
11500   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11501     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11502     plci->li_cmd));
11503
11504   Info = GOOD;
11505   a = plci->adapter;
11506   internal_command = plci->internal_command;
11507   plci->internal_command = 0;
11508   switch (plci->li_cmd)
11509   {
11510   case LI_REQ_CONNECT:
11511   case LI_REQ_DISCONNECT:
11512   case LI_REQ_SILENT_UPDATE:
11513     switch (internal_command)
11514     {
11515     default:
11516       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11517       {
11518         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11519           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11520       }
11521     case MIXER_COMMAND_1:
11522       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11523       {
11524         if (adjust_b_process (Id, plci, Rc) != GOOD)
11525         {
11526           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11527             UnMapId (Id), (char   *)(FILE_), __LINE__));
11528           Info = _FACILITY_NOT_SUPPORTED;
11529           break;
11530         }
11531         if (plci->internal_command)
11532           return;
11533       }
11534       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11535       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11536        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11537         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11538          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11539       {
11540         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11541       }
11542       else
11543       {
11544         do
11545         {
11546           mixer_indication_coefs_set (Id, plci);
11547         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11548       }
11549     case MIXER_COMMAND_2:
11550       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11551        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11552         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11553          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11554       {
11555         if (!xconnect_write_coefs_process (Id, plci, Rc))
11556         {
11557           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11558             UnMapId (Id), (char   *)(FILE_), __LINE__));
11559           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11560           {
11561             do
11562             {
11563               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11564                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11565               i = (plci->li_plci_b_write_pos == 0) ?
11566                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11567             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11568               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11569           }
11570           Info = _FACILITY_NOT_SUPPORTED;
11571           break;
11572         }
11573         if (plci->internal_command)
11574           return;
11575       }
11576       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11577       {
11578         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11579           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11580       }
11581     case MIXER_COMMAND_3:
11582       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11583       {
11584         if (adjust_b_process (Id, plci, Rc) != GOOD)
11585         {
11586           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11587             UnMapId (Id), (char   *)(FILE_), __LINE__));
11588           Info = _FACILITY_NOT_SUPPORTED;
11589           break;
11590         }
11591         if (plci->internal_command)
11592           return;
11593       }
11594       break;
11595     }
11596     break;
11597   }
11598   if ((plci->li_bchannel_id == 0)
11599    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11600   {
11601     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11602       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11603   }
11604   else
11605   {
11606     i = a->li_base + (plci->li_bchannel_id - 1);
11607     li_config_table[i].curchnl = plci->li_channel_bits;
11608     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11609     {
11610       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11611       li_config_table[i].curchnl = plci->li_channel_bits;
11612       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11613       {
11614         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11615         li_config_table[i].curchnl = plci->li_channel_bits;
11616       }
11617     }
11618   }
11619 }
11620
11621
11622 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11623   dword plci_b_id, byte connect, dword li_flags)
11624 {
11625   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11626   PLCI   *plci_b;
11627   DIVA_CAPI_ADAPTER   *a_b;
11628
11629   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11630   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11631   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11632   if (!a->li_pri && (plci->tel == ADV_VOICE)
11633    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11634   {
11635     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11636     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11637       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11638   }
11639   else
11640   {
11641     ch_a_v = ch_a;
11642     ch_a_s = ch_a;
11643   }
11644   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11645   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11646    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11647   {
11648     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11649     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11650       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11651   }
11652   else
11653   {
11654     ch_b_v = ch_b;
11655     ch_b_s = ch_b;
11656   }
11657   if (connect)
11658   {
11659     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11660     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11661     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11662     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11663   }
11664   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11665   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11666   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11667   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668   if (ch_a_v == ch_b_v)
11669   {
11670     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11671     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11672   }
11673   else
11674   {
11675     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11676     {
11677       for (i = 0; i < li_total_channels; i++)
11678       {
11679         if (i != ch_a_v)
11680           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11681       }
11682     }
11683     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11684     {
11685       for (i = 0; i < li_total_channels; i++)
11686       {
11687         if (i != ch_a_s)
11688           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11689       }
11690     }
11691     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11692     {
11693       for (i = 0; i < li_total_channels; i++)
11694       {
11695         if (i != ch_a_v)
11696           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11697       }
11698     }
11699     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11700     {
11701       for (i = 0; i < li_total_channels; i++)
11702       {
11703         if (i != ch_a_s)
11704           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11705       }
11706     }
11707   }
11708   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11709   {
11710     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11711     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11712     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11713     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11714   }
11715   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11716   {
11717     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11718     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11719     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11720     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11721   }
11722   if (li_flags & LI_FLAG_MONITOR_A)
11723   {
11724     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11725     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11726   }
11727   if (li_flags & LI_FLAG_MONITOR_B)
11728   {
11729     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11730     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11731   }
11732   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11733   {
11734     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11735     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11736   }
11737   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11738   {
11739     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11740     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741   }
11742   if (li_flags & LI_FLAG_MIX_A)
11743   {
11744     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11745     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11746   }
11747   if (li_flags & LI_FLAG_MIX_B)
11748   {
11749     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11750     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11751   }
11752   if (ch_a_v != ch_a_s)
11753   {
11754     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11755     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11756   }
11757   if (ch_b_v != ch_b_s)
11758   {
11759     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11760     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11761   }
11762 }
11763
11764
11765 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11766   dword plci_b_id, byte connect, dword li_flags)
11767 {
11768   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11769   PLCI   *plci_b;
11770   DIVA_CAPI_ADAPTER   *a_b;
11771
11772   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11773   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11774   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11775   if (!a->li_pri && (plci->tel == ADV_VOICE)
11776    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11777   {
11778     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11779     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11780       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11781   }
11782   else
11783   {
11784     ch_a_v = ch_a;
11785     ch_a_s = ch_a;
11786   }
11787   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11788   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11789    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11790   {
11791     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11792     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11793       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11794   }
11795   else
11796   {
11797     ch_b_v = ch_b;
11798     ch_b_s = ch_b;
11799   }
11800   if (connect)
11801   {
11802     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11803     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11804     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11805     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11806     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11807     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11808   }
11809   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11810   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11811   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11818   {
11819     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11820     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11821     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11822     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11823   }
11824   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11825   {
11826     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11827     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11828     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11829     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11830   }
11831   if (li_flags & LI2_FLAG_MONITOR_B)
11832   {
11833     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11834     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11835   }
11836   if (li_flags & LI2_FLAG_MIX_B)
11837   {
11838     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11839     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11840   }
11841   if (li_flags & LI2_FLAG_MONITOR_X)
11842     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11843   if (li_flags & LI2_FLAG_MIX_X)
11844     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11845   if (li_flags & LI2_FLAG_LOOP_B)
11846   {
11847     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11848     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11849     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11850     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11851   }
11852   if (li_flags & LI2_FLAG_LOOP_PC)
11853     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11854   if (li_flags & LI2_FLAG_LOOP_X)
11855     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11856   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11857     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11858   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11859     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11860   if (ch_a_v != ch_a_s)
11861   {
11862     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11863     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11864   }
11865   if (ch_b_v != ch_b_s)
11866   {
11867     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11868     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11869   }
11870 }
11871
11872
11873 static word li_check_main_plci (dword Id, PLCI   *plci)
11874 {
11875   if (plci == NULL)
11876   {
11877     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11878       UnMapId (Id), (char   *)(FILE_), __LINE__));
11879     return (_WRONG_IDENTIFIER);
11880   }
11881   if (!plci->State
11882    || !plci->NL.Id || plci->nl_remove_id
11883    || (plci->li_bchannel_id == 0))
11884   {
11885     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11886       UnMapId (Id), (char   *)(FILE_), __LINE__));
11887     return (_WRONG_STATE);
11888   }
11889   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11890   return (GOOD);
11891 }
11892
11893
11894 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11895   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11896 {
11897   byte ctlr_b;
11898   PLCI   *plci_b;
11899
11900   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11901     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11902   {
11903     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11904       UnMapId (Id), (char   *)(FILE_), __LINE__));
11905     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11906     return (NULL);
11907   }
11908   ctlr_b = 0;
11909   if ((plci_b_id & 0x7f) != 0)
11910   {
11911     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11912     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11913       ctlr_b = 0;
11914   }
11915   if ((ctlr_b == 0)
11916    || (((plci_b_id >> 8) & 0xff) == 0)
11917    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11918   {
11919     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11920       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11921     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11922     return (NULL);
11923   }
11924   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11925   if (!plci_b->State
11926    || !plci_b->NL.Id || plci_b->nl_remove_id
11927    || (plci_b->li_bchannel_id == 0))
11928   {
11929     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11930       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11931     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11932     return (NULL);
11933   }
11934   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11935   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11936     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11937    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11938     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11939   {
11940     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11941       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11942     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11943     return (NULL);
11944   }
11945   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11946     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11947   {
11948     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11949       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11950     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11951     return (NULL);
11952   }
11953   return (plci_b);
11954 }
11955
11956
11957 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11958   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11959 {
11960   byte ctlr_b;
11961   PLCI   *plci_b;
11962
11963   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11964     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11965   {
11966     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11967       UnMapId (Id), (char   *)(FILE_), __LINE__));
11968     PUT_WORD (p_result, _WRONG_STATE);
11969     return (NULL);
11970   }
11971   ctlr_b = 0;
11972   if ((plci_b_id & 0x7f) != 0)
11973   {
11974     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11975     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11976       ctlr_b = 0;
11977   }
11978   if ((ctlr_b == 0)
11979    || (((plci_b_id >> 8) & 0xff) == 0)
11980    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11981   {
11982     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11983       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11984     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11985     return (NULL);
11986   }
11987   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11988   if (!plci_b->State
11989    || !plci_b->NL.Id || plci_b->nl_remove_id
11990    || (plci_b->li_bchannel_id == 0)
11991    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11992   {
11993     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11994       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11995     PUT_WORD (p_result, _WRONG_STATE);
11996     return (NULL);
11997   }
11998   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11999     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12000    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12001     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12002   {
12003     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12004       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12005     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12006     return (NULL);
12007   }
12008   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12009     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12010   {
12011     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12012       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12013     PUT_WORD (p_result, _WRONG_STATE);
12014     return (NULL);
12015   }
12016   return (plci_b);
12017 }
12018
12019
12020 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12021 {
12022   word Info;
12023   word i;
12024   dword d, li_flags, plci_b_id;
12025   PLCI   *plci_b;
12026     API_PARSE li_parms[3];
12027     API_PARSE li_req_parms[3];
12028     API_PARSE li_participant_struct[2];
12029     API_PARSE li_participant_parms[3];
12030   word participant_parms_pos;
12031   byte result_buffer[32];
12032   byte   *result;
12033   word result_pos;
12034   word plci_b_write_pos;
12035
12036   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12037     UnMapId (Id), (char   *)(FILE_), __LINE__));
12038
12039   Info = GOOD;
12040   result = result_buffer;
12041   result_buffer[0] = 0;
12042   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12043   {
12044     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12045       UnMapId (Id), (char   *)(FILE_), __LINE__));
12046     Info = _FACILITY_NOT_SUPPORTED;
12047   }
12048   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12049   {
12050     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12051       UnMapId (Id), (char   *)(FILE_), __LINE__));
12052     Info = _WRONG_MESSAGE_FORMAT;
12053   }
12054   else
12055   {
12056     result_buffer[0] = 3;
12057     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12058     result_buffer[3] = 0;
12059     switch (GET_WORD (li_parms[0].info))
12060     {
12061     case LI_GET_SUPPORTED_SERVICES:
12062       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12063       {
12064         result_buffer[0] = 17;
12065         result_buffer[3] = 14;
12066         PUT_WORD (&result_buffer[4], GOOD);
12067         d = 0;
12068         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12069           d |= LI_CONFERENCING_SUPPORTED;
12070         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12071           d |= LI_MONITORING_SUPPORTED;
12072         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12073           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12074         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12075           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12076         PUT_DWORD (&result_buffer[6], d);
12077         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12078         {
12079           d = 0;
12080           for (i = 0; i < li_total_channels; i++)
12081           {
12082             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12083              && (li_config_table[i].adapter->li_pri
12084               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12085             {
12086               d++;
12087             }
12088           }
12089         }
12090         else
12091         {
12092           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12093         }
12094         PUT_DWORD (&result_buffer[10], d / 2);
12095         PUT_DWORD (&result_buffer[14], d);
12096       }
12097       else
12098       {
12099         result_buffer[0] = 25;
12100         result_buffer[3] = 22;
12101         PUT_WORD (&result_buffer[4], GOOD);
12102         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12103         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12104           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12105         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12106           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12107         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12108           d |= LI2_PC_LOOPING_SUPPORTED;
12109         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12110           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12111         PUT_DWORD (&result_buffer[6], d);
12112         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12113         PUT_DWORD (&result_buffer[10], d / 2);
12114         PUT_DWORD (&result_buffer[14], d - 1);
12115         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12116         {
12117           d = 0;
12118           for (i = 0; i < li_total_channels; i++)
12119           {
12120             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12121              && (li_config_table[i].adapter->li_pri
12122               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12123             {
12124               d++;
12125             }
12126           }
12127         }
12128         PUT_DWORD (&result_buffer[18], d / 2);
12129         PUT_DWORD (&result_buffer[22], d - 1);
12130       }
12131       break;
12132
12133     case LI_REQ_CONNECT:
12134       if (li_parms[1].length == 8)
12135       {
12136         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12137         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12138         {
12139           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12140             UnMapId (Id), (char   *)(FILE_), __LINE__));
12141           Info = _WRONG_MESSAGE_FORMAT;
12142           break;
12143         }
12144         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12145         li_flags = GET_DWORD (li_req_parms[1].info);
12146         Info = li_check_main_plci (Id, plci);
12147         result_buffer[0] = 9;
12148         result_buffer[3] = 6;
12149         PUT_DWORD (&result_buffer[4], plci_b_id);
12150         PUT_WORD (&result_buffer[8], GOOD);
12151         if (Info != GOOD)
12152           break;
12153         result = plci->saved_msg.info;
12154         for (i = 0; i <= result_buffer[0]; i++)
12155           result[i] = result_buffer[i];
12156         plci_b_write_pos = plci->li_plci_b_write_pos;
12157         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12158         if (plci_b == NULL)
12159           break;
12160         li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12161         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12162         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12163         plci->li_plci_b_write_pos = plci_b_write_pos;
12164       }
12165       else
12166       {
12167         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12168         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12169         {
12170           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12171             UnMapId (Id), (char   *)(FILE_), __LINE__));
12172           Info = _WRONG_MESSAGE_FORMAT;
12173           break;
12174         }
12175         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12176         Info = li_check_main_plci (Id, plci);
12177         result_buffer[0] = 7;
12178         result_buffer[3] = 4;
12179         PUT_WORD (&result_buffer[4], Info);
12180         result_buffer[6] = 0;
12181         if (Info != GOOD)
12182           break;
12183         result = plci->saved_msg.info;
12184         for (i = 0; i <= result_buffer[0]; i++)
12185           result[i] = result_buffer[i];
12186         plci_b_write_pos = plci->li_plci_b_write_pos;
12187         participant_parms_pos = 0;
12188         result_pos = 7;
12189         li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12190         while (participant_parms_pos < li_req_parms[1].length)
12191         {
12192           result[result_pos] = 6;
12193           result_pos += 7;
12194           PUT_DWORD (&result[result_pos - 6], 0);
12195           PUT_WORD (&result[result_pos - 2], GOOD);
12196           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12197             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12198           {
12199             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12200               UnMapId (Id), (char   *)(FILE_), __LINE__));
12201             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12202             break;
12203           }
12204           if (api_parse (&li_participant_struct[0].info[1],
12205             li_participant_struct[0].length, "dd", li_participant_parms))
12206           {
12207             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12208               UnMapId (Id), (char   *)(FILE_), __LINE__));
12209             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210             break;
12211           }
12212           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12213           li_flags = GET_DWORD (li_participant_parms[1].info);
12214           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12215           if (sizeof(result) - result_pos < 7)
12216           {
12217             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12218               UnMapId (Id), (char   *)(FILE_), __LINE__));
12219             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12220             break;
12221           }
12222           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12223           if (plci_b != NULL)
12224           {
12225             li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12226             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12227               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12228               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12229             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12230           }
12231           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12232             (&li_req_parms[1].info[1]));
12233         }
12234         result[0] = (byte)(result_pos - 1);
12235         result[3] = (byte)(result_pos - 4);
12236         result[6] = (byte)(result_pos - 7);
12237         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12238         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12239          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12240         {
12241           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12242           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12243         }
12244         else
12245           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12246         plci->li_plci_b_write_pos = plci_b_write_pos;
12247       }
12248       mixer_calculate_coefs (a);
12249       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12250       mixer_notify_update (plci, true);
12251       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12252         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12253       plci->command = 0;
12254       plci->li_cmd = GET_WORD (li_parms[0].info);
12255       start_internal_command (Id, plci, mixer_command);
12256       return (false);
12257
12258     case LI_REQ_DISCONNECT:
12259       if (li_parms[1].length == 4)
12260       {
12261         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12262         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12263         {
12264           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12265             UnMapId (Id), (char   *)(FILE_), __LINE__));
12266           Info = _WRONG_MESSAGE_FORMAT;
12267           break;
12268         }
12269         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12270         Info = li_check_main_plci (Id, plci);
12271         result_buffer[0] = 9;
12272         result_buffer[3] = 6;
12273         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12274         PUT_WORD (&result_buffer[8], GOOD);
12275         if (Info != GOOD)
12276           break;
12277         result = plci->saved_msg.info;
12278         for (i = 0; i <= result_buffer[0]; i++)
12279           result[i] = result_buffer[i];
12280         plci_b_write_pos = plci->li_plci_b_write_pos;
12281         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12282         if (plci_b == NULL)
12283           break;
12284         li_update_connect (Id, a, plci, plci_b_id, false, 0);
12285         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12286         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12287         plci->li_plci_b_write_pos = plci_b_write_pos;
12288       }
12289       else
12290       {
12291         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12292         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12293         {
12294           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12295             UnMapId (Id), (char   *)(FILE_), __LINE__));
12296           Info = _WRONG_MESSAGE_FORMAT;
12297           break;
12298         }
12299         Info = li_check_main_plci (Id, plci);
12300         result_buffer[0] = 7;
12301         result_buffer[3] = 4;
12302         PUT_WORD (&result_buffer[4], Info);
12303         result_buffer[6] = 0;
12304         if (Info != GOOD)
12305           break;
12306         result = plci->saved_msg.info;
12307         for (i = 0; i <= result_buffer[0]; i++)
12308           result[i] = result_buffer[i];
12309         plci_b_write_pos = plci->li_plci_b_write_pos;
12310         participant_parms_pos = 0;
12311         result_pos = 7;
12312         while (participant_parms_pos < li_req_parms[0].length)
12313         {
12314           result[result_pos] = 6;
12315           result_pos += 7;
12316           PUT_DWORD (&result[result_pos - 6], 0);
12317           PUT_WORD (&result[result_pos - 2], GOOD);
12318           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12319             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12320           {
12321             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12322               UnMapId (Id), (char   *)(FILE_), __LINE__));
12323             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12324             break;
12325           }
12326           if (api_parse (&li_participant_struct[0].info[1],
12327             li_participant_struct[0].length, "d", li_participant_parms))
12328           {
12329             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12330               UnMapId (Id), (char   *)(FILE_), __LINE__));
12331             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12332             break;
12333           }
12334           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12335           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12336           if (sizeof(result) - result_pos < 7)
12337           {
12338             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12339               UnMapId (Id), (char   *)(FILE_), __LINE__));
12340             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12341             break;
12342           }
12343           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12344           if (plci_b != NULL)
12345           {
12346             li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12347             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12348             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12349           }
12350           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12351             (&li_req_parms[0].info[1]));
12352         }
12353         result[0] = (byte)(result_pos - 1);
12354         result[3] = (byte)(result_pos - 4);
12355         result[6] = (byte)(result_pos - 7);
12356         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12357         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12358          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12359         {
12360           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12361           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12362         }
12363         else
12364           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12365         plci->li_plci_b_write_pos = plci_b_write_pos;
12366       }
12367       mixer_calculate_coefs (a);
12368       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12369       mixer_notify_update (plci, true);
12370       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12371         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12372       plci->command = 0;
12373       plci->li_cmd = GET_WORD (li_parms[0].info);
12374       start_internal_command (Id, plci, mixer_command);
12375       return (false);
12376
12377     case LI_REQ_SILENT_UPDATE:
12378       if (!plci || !plci->State
12379        || !plci->NL.Id || plci->nl_remove_id
12380        || (plci->li_bchannel_id == 0)
12381        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12382       {
12383         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12384           UnMapId (Id), (char   *)(FILE_), __LINE__));
12385         return (false);
12386       }
12387       plci_b_write_pos = plci->li_plci_b_write_pos;
12388       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12389         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12390       {
12391         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12392           UnMapId (Id), (char   *)(FILE_), __LINE__));
12393         return (false);
12394       }
12395       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12396       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12397        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12398       {
12399         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12400         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12401       }
12402       else
12403         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12404       plci->li_plci_b_write_pos = plci_b_write_pos;
12405       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12406       plci->command = 0;
12407       plci->li_cmd = GET_WORD (li_parms[0].info);
12408       start_internal_command (Id, plci, mixer_command);
12409       return (false);
12410
12411     default:
12412       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12413         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12414       Info = _FACILITY_NOT_SUPPORTED;
12415     }
12416   }
12417   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12418     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12419   return (false);
12420 }
12421
12422
12423 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12424 {
12425   dword d;
12426   DIVA_CAPI_ADAPTER   *a;
12427     byte result[12];
12428
12429   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12430     UnMapId (Id), (char   *)(FILE_), __LINE__));
12431
12432   a = plci->adapter;
12433   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12434   {
12435     do
12436     {
12437       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12438       if (!(d & LI_PLCI_B_SKIP_FLAG))
12439       {
12440         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12441         {
12442           if (d & LI_PLCI_B_DISC_FLAG)
12443           {
12444             result[0] = 5;
12445             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12446             result[3] = 2;
12447             PUT_WORD (&result[4], _LI_USER_INITIATED);
12448           }
12449           else
12450           {
12451             result[0] = 7;
12452             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12453             result[3] = 4;
12454             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12455           }
12456         }
12457         else
12458         {
12459           if (d & LI_PLCI_B_DISC_FLAG)
12460           {
12461             result[0] = 9;
12462             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12463             result[3] = 6;
12464             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12465             PUT_WORD (&result[8], _LI_USER_INITIATED);
12466           }
12467           else
12468           {
12469             result[0] = 7;
12470             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12471             result[3] = 4;
12472             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12473           }
12474         }
12475         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12476           "ws", SELECTOR_LINE_INTERCONNECT, result);
12477       }
12478       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12479         0 : plci->li_plci_b_read_pos + 1;
12480     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12481   }
12482 }
12483
12484
12485 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12486 {
12487   word i, j, ch;
12488   struct xconnect_transfer_address_s s,   *p;
12489   DIVA_CAPI_ADAPTER   *a;
12490
12491   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12492     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12493
12494   a = plci->adapter;
12495   i = 1;
12496   for (i = 1; i < length; i += 16)
12497   {
12498     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12499     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12500     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12501     ch = msg[i+12] | (msg[i+13] << 8);
12502     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12503     if (!a->li_pri && (plci->li_bchannel_id == 2))
12504       j = 1 - j;
12505     j += a->li_base;
12506     if (ch & XCONNECT_CHANNEL_PORT_PC)
12507       p = &(li_config_table[j].send_pc);
12508     else
12509       p = &(li_config_table[j].send_b);
12510     p->card_address.low = s.card_address.low;
12511     p->card_address.high = s.card_address.high;
12512     p->offset = s.offset;
12513     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12514   }
12515   if (plci->internal_command_queue[0]
12516    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12517     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12518     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12519   {
12520     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12521     if (!plci->internal_command)
12522       next_internal_command (Id, plci);
12523   }
12524   mixer_notify_update (plci, true);
12525 }
12526
12527
12528 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12529 {
12530
12531   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12532     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12533
12534 }
12535
12536
12537 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12538 {
12539   word plci_b_write_pos;
12540
12541   plci_b_write_pos = plci->li_plci_b_write_pos;
12542   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12543     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12544   {
12545     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12546       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12547       (char   *)(FILE_), __LINE__));
12548     return (false);
12549   }
12550   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12551   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12552   plci->li_plci_b_write_pos = plci_b_write_pos;
12553   return (true);
12554 }
12555
12556
12557 static void mixer_remove (PLCI   *plci)
12558 {
12559   DIVA_CAPI_ADAPTER   *a;
12560   PLCI   *notify_plci;
12561   dword plci_b_id;
12562   word i, j;
12563
12564   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12565     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12566     (char   *)(FILE_), __LINE__));
12567
12568   a = plci->adapter;
12569   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12570   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12571   {
12572     if ((plci->li_bchannel_id != 0)
12573      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12574     {
12575       i = a->li_base + (plci->li_bchannel_id - 1);
12576       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12577       {
12578         for (j = 0; j < li_total_channels; j++)
12579         {
12580           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12581            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12582           {
12583             notify_plci = li_config_table[j].plci;
12584             if ((notify_plci != NULL)
12585              && (notify_plci != plci)
12586              && (notify_plci->appl != NULL)
12587              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12588              && (notify_plci->State)
12589              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12590             {
12591               mixer_notify_source_removed (notify_plci, plci_b_id);
12592             }
12593           }
12594         }
12595         mixer_clear_config (plci);
12596         mixer_calculate_coefs (a);
12597         mixer_notify_update (plci, true);
12598       }
12599       li_config_table[i].plci = NULL;
12600       plci->li_bchannel_id = 0;
12601     }
12602   }
12603 }
12604
12605
12606 /*------------------------------------------------------------------*/
12607 /* Echo canceller facilities                                        */
12608 /*------------------------------------------------------------------*/
12609
12610
12611 static void ec_write_parameters (PLCI   *plci)
12612 {
12613   word w;
12614     byte parameter_buffer[6];
12615
12616   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12617     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12618     (char   *)(FILE_), __LINE__));
12619
12620   parameter_buffer[0] = 5;
12621   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12622   PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12623   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12624   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12625   PUT_WORD (&parameter_buffer[4], w);
12626   add_p (plci, FTY, parameter_buffer);
12627   sig_req (plci, TEL_CTRL, 0);
12628   send_req (plci);
12629 }
12630
12631
12632 static void ec_clear_config (PLCI   *plci)
12633 {
12634
12635   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12636     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12637     (char   *)(FILE_), __LINE__));
12638
12639   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12640     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12641   plci->ec_tail_length = 0;
12642 }
12643
12644
12645 static void ec_prepare_switch (dword Id, PLCI   *plci)
12646 {
12647
12648   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12649     UnMapId (Id), (char   *)(FILE_), __LINE__));
12650
12651 }
12652
12653
12654 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12655 {
12656
12657   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12658     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12659
12660   return (GOOD);
12661 }
12662
12663
12664 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12665 {
12666   word Info;
12667
12668   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12669     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12670
12671   Info = GOOD;
12672   if (plci->B1_facilities & B1_FACILITY_EC)
12673   {
12674     switch (plci->adjust_b_state)
12675     {
12676     case ADJUST_B_RESTORE_EC_1:
12677       plci->internal_command = plci->adjust_b_command;
12678       if (plci->sig_req)
12679       {
12680         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12681         break;
12682       }
12683       ec_write_parameters (plci);
12684       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12685       break;
12686     case ADJUST_B_RESTORE_EC_2:
12687       if ((Rc != OK) && (Rc != OK_FC))
12688       {
12689         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12690           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12691         Info = _WRONG_STATE;
12692         break;
12693       }
12694       break;
12695     }
12696   }
12697   return (Info);
12698 }
12699
12700
12701 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12702 {
12703   word internal_command, Info;
12704     byte result[8];
12705
12706   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12707     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12708     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12709
12710   Info = GOOD;
12711   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12712   {
12713     result[0] = 2;
12714     PUT_WORD (&result[1], EC_SUCCESS);
12715   }
12716   else
12717   {
12718     result[0] = 5;
12719     PUT_WORD (&result[1], plci->ec_cmd);
12720     result[3] = 2;
12721     PUT_WORD (&result[4], GOOD);
12722   }
12723   internal_command = plci->internal_command;
12724   plci->internal_command = 0;
12725   switch (plci->ec_cmd)
12726   {
12727   case EC_ENABLE_OPERATION:
12728   case EC_FREEZE_COEFFICIENTS:
12729   case EC_RESUME_COEFFICIENT_UPDATE:
12730   case EC_RESET_COEFFICIENTS:
12731     switch (internal_command)
12732     {
12733     default:
12734       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12735         B1_FACILITY_EC), EC_COMMAND_1);
12736     case EC_COMMAND_1:
12737       if (adjust_b_process (Id, plci, Rc) != GOOD)
12738       {
12739         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12740           UnMapId (Id), (char   *)(FILE_), __LINE__));
12741         Info = _FACILITY_NOT_SUPPORTED;
12742         break;
12743       }
12744       if (plci->internal_command)
12745         return;
12746     case EC_COMMAND_2:
12747       if (plci->sig_req)
12748       {
12749         plci->internal_command = EC_COMMAND_2;
12750         return;
12751       }
12752       plci->internal_command = EC_COMMAND_3;
12753       ec_write_parameters (plci);
12754       return;
12755     case EC_COMMAND_3:
12756       if ((Rc != OK) && (Rc != OK_FC))
12757       {
12758         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12759           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12760         Info = _FACILITY_NOT_SUPPORTED;
12761         break;
12762       }
12763       break;
12764     }
12765     break;
12766
12767   case EC_DISABLE_OPERATION:
12768     switch (internal_command)
12769     {
12770     default:
12771     case EC_COMMAND_1:
12772       if (plci->B1_facilities & B1_FACILITY_EC)
12773       {
12774         if (plci->sig_req)
12775         {
12776           plci->internal_command = EC_COMMAND_1;
12777           return;
12778         }
12779         plci->internal_command = EC_COMMAND_2;
12780         ec_write_parameters (plci);
12781         return;
12782       }
12783       Rc = OK;
12784     case EC_COMMAND_2:
12785       if ((Rc != OK) && (Rc != OK_FC))
12786       {
12787         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12788           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12789         Info = _FACILITY_NOT_SUPPORTED;
12790         break;
12791       }
12792       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12793         ~B1_FACILITY_EC), EC_COMMAND_3);
12794     case EC_COMMAND_3:
12795       if (adjust_b_process (Id, plci, Rc) != GOOD)
12796       {
12797         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12798           UnMapId (Id), (char   *)(FILE_), __LINE__));
12799         Info = _FACILITY_NOT_SUPPORTED;
12800         break;
12801       }
12802       if (plci->internal_command)
12803         return;
12804       break;
12805     }
12806     break;
12807   }
12808   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12809     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12810     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12811 }
12812
12813
12814 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12815 {
12816   word Info;
12817   word opt;
12818     API_PARSE ec_parms[3];
12819     byte result[16];
12820
12821   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12822     UnMapId (Id), (char   *)(FILE_), __LINE__));
12823
12824   Info = GOOD;
12825   result[0] = 0;
12826   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12827   {
12828     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12829       UnMapId (Id), (char   *)(FILE_), __LINE__));
12830     Info = _FACILITY_NOT_SUPPORTED;
12831   }
12832   else
12833   {
12834     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12835     {
12836       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12837       {
12838         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12839           UnMapId (Id), (char   *)(FILE_), __LINE__));
12840         Info = _WRONG_MESSAGE_FORMAT;
12841       }
12842       else
12843       {
12844         if (plci == NULL)
12845         {
12846           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12847             UnMapId (Id), (char   *)(FILE_), __LINE__));
12848           Info = _WRONG_IDENTIFIER;
12849         }
12850         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12851         {
12852           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12853             UnMapId (Id), (char   *)(FILE_), __LINE__));
12854           Info = _WRONG_STATE;
12855         }
12856         else
12857         {
12858           plci->command = 0;
12859           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12860           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12861           result[0] = 2;
12862           PUT_WORD (&result[1], EC_SUCCESS);
12863           if (msg[1].length >= 4)
12864           {
12865             opt = GET_WORD (&ec_parms[0].info[2]);
12866             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12867               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12868             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12869               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12870             if (opt & EC_DETECT_DISABLE_TONE)
12871               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12872             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12873               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12874             if (msg[1].length >= 6)
12875             {
12876               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12877             }
12878           }
12879           switch (plci->ec_cmd)
12880           {
12881           case EC_ENABLE_OPERATION:
12882             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12883             start_internal_command (Id, plci, ec_command);
12884             return (false);
12885
12886           case EC_DISABLE_OPERATION:
12887             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12888               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12889               LEC_RESET_COEFFICIENTS;
12890             start_internal_command (Id, plci, ec_command);
12891             return (false);
12892
12893           case EC_FREEZE_COEFFICIENTS:
12894             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12895             start_internal_command (Id, plci, ec_command);
12896             return (false);
12897
12898           case EC_RESUME_COEFFICIENT_UPDATE:
12899             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12900             start_internal_command (Id, plci, ec_command);
12901             return (false);
12902
12903           case EC_RESET_COEFFICIENTS:
12904             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12905             start_internal_command (Id, plci, ec_command);
12906             return (false);
12907
12908           default:
12909             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12910               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12911             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12912           }
12913         }
12914       }
12915     }
12916     else
12917     {
12918       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12919       {
12920         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12921           UnMapId (Id), (char   *)(FILE_), __LINE__));
12922         Info = _WRONG_MESSAGE_FORMAT;
12923       }
12924       else
12925       {
12926         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12927         {
12928           result[0] = 11;
12929           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12930           result[3] = 8;
12931           PUT_WORD (&result[4], GOOD);
12932           PUT_WORD (&result[6], 0x0007);
12933           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12934           PUT_WORD (&result[10], 0);
12935         }
12936         else if (plci == NULL)
12937         {
12938           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12939             UnMapId (Id), (char   *)(FILE_), __LINE__));
12940           Info = _WRONG_IDENTIFIER;
12941         }
12942         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12943         {
12944           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12945             UnMapId (Id), (char   *)(FILE_), __LINE__));
12946           Info = _WRONG_STATE;
12947         }
12948         else
12949         {
12950           plci->command = 0;
12951           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12952           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12953           result[0] = 5;
12954           PUT_WORD (&result[1], plci->ec_cmd);
12955           result[3] = 2;
12956           PUT_WORD (&result[4], GOOD);
12957           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12958             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12959           plci->ec_tail_length = 0;
12960           if (ec_parms[1].length >= 2)
12961           {
12962             opt = GET_WORD (&ec_parms[1].info[1]);
12963             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12964               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12965             if (opt & EC_DETECT_DISABLE_TONE)
12966               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12967             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12968               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12969             if (ec_parms[1].length >= 4)
12970             {
12971               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12972             }
12973           }
12974           switch (plci->ec_cmd)
12975           {
12976           case EC_ENABLE_OPERATION:
12977             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12978             start_internal_command (Id, plci, ec_command);
12979             return (false);
12980
12981           case EC_DISABLE_OPERATION:
12982             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12983               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12984               LEC_RESET_COEFFICIENTS;
12985             start_internal_command (Id, plci, ec_command);
12986             return (false);
12987
12988           default:
12989             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12990               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12991             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12992           }
12993         }
12994       }
12995     }
12996   }
12997   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12998     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12999     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13000   return (false);
13001 }
13002
13003
13004 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13005 {
13006     byte result[8];
13007
13008   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13009     UnMapId (Id), (char   *)(FILE_), __LINE__));
13010
13011   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13012   {
13013     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13014     {
13015       result[0] = 2;
13016       PUT_WORD (&result[1], 0);
13017       switch (msg[1])
13018       {
13019       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13020         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13021         break;
13022       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13023         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13024         break;
13025       case LEC_DISABLE_RELEASED:
13026         PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13027         break;
13028       }
13029     }
13030     else
13031     {
13032       result[0] = 5;
13033       PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13034       result[3] = 2;
13035       PUT_WORD (&result[4], 0);
13036       switch (msg[1])
13037       {
13038       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13039         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13040         break;
13041       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13042         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13043         break;
13044       case LEC_DISABLE_RELEASED:
13045         PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13046         break;
13047       }
13048     }
13049     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13050       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13051   }
13052 }
13053
13054
13055
13056 /*------------------------------------------------------------------*/
13057 /* Advanced voice                                                   */
13058 /*------------------------------------------------------------------*/
13059
13060 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13061 {
13062   DIVA_CAPI_ADAPTER   *a;
13063   word i;
13064   byte *p;
13065
13066   word w, n, j, k;
13067   byte ch_map[MIXER_CHANNELS_BRI];
13068
13069     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13070
13071   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13072     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13073     (char   *)(FILE_), __LINE__, write_command));
13074
13075   a = plci->adapter;
13076   p = coef_buffer + 1;
13077   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13078   i = 0;
13079   while (i + sizeof(word) <= a->adv_voice_coef_length)
13080   {
13081     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13082     p += 2;
13083     i += 2;
13084   }
13085   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13086   {
13087     PUT_WORD (p, 0x8000);
13088     p += 2;
13089     i += 2;
13090   }
13091
13092   if (!a->li_pri && (plci->li_bchannel_id == 0))
13093   {
13094     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13095     {
13096       plci->li_bchannel_id = 1;
13097       li_config_table[a->li_base].plci = plci;
13098       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13099         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13100         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13101     }
13102     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13103     {
13104       plci->li_bchannel_id = 2;
13105       li_config_table[a->li_base + 1].plci = plci;
13106       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13107         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13108         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13109     }
13110   }
13111   if (!a->li_pri && (plci->li_bchannel_id != 0)
13112    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13113   {
13114     i = a->li_base + (plci->li_bchannel_id - 1);
13115     switch (write_command)
13116     {
13117     case ADV_VOICE_WRITE_ACTIVATION:
13118       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13119       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13120       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13121       {
13122         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13123         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13124       }
13125       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13126       {
13127         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13128         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13129         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13130         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13131       }
13132       mixer_calculate_coefs (a);
13133       li_config_table[i].curchnl = li_config_table[i].channel;
13134       li_config_table[j].curchnl = li_config_table[j].channel;
13135       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13136         li_config_table[k].curchnl = li_config_table[k].channel;
13137       break;
13138
13139     case ADV_VOICE_WRITE_DEACTIVATION:
13140       for (j = 0; j < li_total_channels; j++)
13141       {
13142         li_config_table[i].flag_table[j] = 0;
13143         li_config_table[j].flag_table[i] = 0;
13144       }
13145       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13146       for (j = 0; j < li_total_channels; j++)
13147       {
13148         li_config_table[k].flag_table[j] = 0;
13149         li_config_table[j].flag_table[k] = 0;
13150       }
13151       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13152       {
13153         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13154         for (j = 0; j < li_total_channels; j++)
13155         {
13156           li_config_table[k].flag_table[j] = 0;
13157           li_config_table[j].flag_table[k] = 0;
13158         }
13159       }
13160       mixer_calculate_coefs (a);
13161       break;
13162     }
13163     if (plci->B1_facilities & B1_FACILITY_MIXER)
13164     {
13165       w = 0;
13166       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13167         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13168       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13169         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13170       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13171         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13172       *(p++) = (byte) w;
13173       *(p++) = (byte)(w >> 8);
13174       for (j = 0; j < sizeof(ch_map); j += 2)
13175       {
13176         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13177         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13178       }
13179       for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13180       {
13181         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13182         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13183         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13184         {
13185           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13186           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13187           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13188         }
13189         else
13190         {
13191           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13192             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13193         }
13194       }
13195     }
13196     else
13197     {
13198       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13199         *(p++) = a->adv_voice_coef_buffer[i];
13200     }
13201   }
13202   else
13203
13204   {
13205     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13206       *(p++) = a->adv_voice_coef_buffer[i];
13207   }
13208   coef_buffer[0] = (p - coef_buffer) - 1;
13209   add_p (plci, FTY, coef_buffer);
13210   sig_req (plci, TEL_CTRL, 0);
13211   send_req (plci);
13212 }
13213
13214
13215 static void adv_voice_clear_config (PLCI   *plci)
13216 {
13217   DIVA_CAPI_ADAPTER   *a;
13218
13219   word i, j;
13220
13221
13222   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13223     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13224     (char   *)(FILE_), __LINE__));
13225
13226   a = plci->adapter;
13227   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13228   {
13229     a->adv_voice_coef_length = 0;
13230
13231     if (!a->li_pri && (plci->li_bchannel_id != 0)
13232      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13233     {
13234       i = a->li_base + (plci->li_bchannel_id - 1);
13235       li_config_table[i].curchnl = 0;
13236       li_config_table[i].channel = 0;
13237       li_config_table[i].chflags = 0;
13238       for (j = 0; j < li_total_channels; j++)
13239       {
13240         li_config_table[i].flag_table[j] = 0;
13241         li_config_table[j].flag_table[i] = 0;
13242         li_config_table[i].coef_table[j] = 0;
13243         li_config_table[j].coef_table[i] = 0;
13244       }
13245       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13246       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13247       li_config_table[i].curchnl = 0;
13248       li_config_table[i].channel = 0;
13249       li_config_table[i].chflags = 0;
13250       for (j = 0; j < li_total_channels; j++)
13251       {
13252         li_config_table[i].flag_table[j] = 0;
13253         li_config_table[j].flag_table[i] = 0;
13254         li_config_table[i].coef_table[j] = 0;
13255         li_config_table[j].coef_table[i] = 0;
13256       }
13257       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13258       {
13259         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13260         li_config_table[i].curchnl = 0;
13261         li_config_table[i].channel = 0;
13262         li_config_table[i].chflags = 0;
13263         for (j = 0; j < li_total_channels; j++)
13264         {
13265           li_config_table[i].flag_table[j] = 0;
13266           li_config_table[j].flag_table[i] = 0;
13267           li_config_table[i].coef_table[j] = 0;
13268           li_config_table[j].coef_table[i] = 0;
13269         }
13270       }
13271     }
13272
13273   }
13274 }
13275
13276
13277 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13278 {
13279
13280   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13281     UnMapId (Id), (char   *)(FILE_), __LINE__));
13282
13283 }
13284
13285
13286 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13287 {
13288
13289   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13290     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13291
13292   return (GOOD);
13293 }
13294
13295
13296 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13297 {
13298   DIVA_CAPI_ADAPTER   *a;
13299   word Info;
13300
13301   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13302     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13303
13304   Info = GOOD;
13305   a = plci->adapter;
13306   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13307    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13308   {
13309     switch (plci->adjust_b_state)
13310     {
13311     case ADJUST_B_RESTORE_VOICE_1:
13312       plci->internal_command = plci->adjust_b_command;
13313       if (plci->sig_req)
13314       {
13315         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13316         break;
13317       }
13318       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13319       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13320       break;
13321     case ADJUST_B_RESTORE_VOICE_2:
13322       if ((Rc != OK) && (Rc != OK_FC))
13323       {
13324         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13325           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13326         Info = _WRONG_STATE;
13327         break;
13328       }
13329       break;
13330     }
13331   }
13332   return (Info);
13333 }
13334
13335
13336
13337
13338 /*------------------------------------------------------------------*/
13339 /* B1 resource switching                                            */
13340 /*------------------------------------------------------------------*/
13341
13342 static byte b1_facilities_table[] =
13343 {
13344   0x00,  /* 0  No bchannel resources      */
13345   0x00,  /* 1  Codec (automatic law)      */
13346   0x00,  /* 2  Codec (A-law)              */
13347   0x00,  /* 3  Codec (y-law)              */
13348   0x00,  /* 4  HDLC for X.21              */
13349   0x00,  /* 5  HDLC                       */
13350   0x00,  /* 6  External Device 0          */
13351   0x00,  /* 7  External Device 1          */
13352   0x00,  /* 8  HDLC 56k                   */
13353   0x00,  /* 9  Transparent                */
13354   0x00,  /* 10 Loopback to network        */
13355   0x00,  /* 11 Test pattern to net        */
13356   0x00,  /* 12 Rate adaptation sync       */
13357   0x00,  /* 13 Rate adaptation async      */
13358   0x00,  /* 14 R-Interface                */
13359   0x00,  /* 15 HDLC 128k leased line      */
13360   0x00,  /* 16 FAX                        */
13361   0x00,  /* 17 Modem async                */
13362   0x00,  /* 18 Modem sync HDLC            */
13363   0x00,  /* 19 V.110 async HDLC           */
13364   0x12,  /* 20 Adv voice (Trans,mixer)    */
13365   0x00,  /* 21 Codec connected to IC      */
13366   0x0c,  /* 22 Trans,DTMF                 */
13367   0x1e,  /* 23 Trans,DTMF+mixer           */
13368   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13369   0x13,  /* 25 Trans,mixer+local          */
13370   0x12,  /* 26 HDLC,mixer                 */
13371   0x12,  /* 27 HDLC 56k,mixer             */
13372   0x2c,  /* 28 Trans,LEC+DTMF             */
13373   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13374   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13375   0x2c,  /* 31 RTP,LEC+DTMF               */
13376   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13377   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13378   0x00,  /* 34 Signaling task             */
13379   0x00,  /* 35 PIAFS                      */
13380   0x0c,  /* 36 Trans,DTMF+TONE            */
13381   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13382   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13383 };
13384
13385
13386 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13387 {
13388   word b1_facilities;
13389
13390   b1_facilities = b1_facilities_table[b1_resource];
13391   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13392   {
13393
13394     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13395        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13396
13397     {
13398       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13399         b1_facilities |= B1_FACILITY_DTMFX;
13400       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13401         b1_facilities |= B1_FACILITY_DTMFR;
13402     }
13403   }
13404   if ((b1_resource == 17) || (b1_resource == 18))
13405   {
13406     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13407       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13408   }
13409 /*
13410   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13411     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13412     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13413 */
13414   return (b1_facilities);
13415 }
13416
13417
13418 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13419 {
13420   byte b;
13421
13422   switch (b1_resource)
13423   {
13424   case 5:
13425   case 26:
13426     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13427       b = 26;
13428     else
13429       b = 5;
13430     break;
13431
13432   case 8:
13433   case 27:
13434     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13435       b = 27;
13436     else
13437       b = 8;
13438     break;
13439
13440   case 9:
13441   case 20:
13442   case 22:
13443   case 23:
13444   case 24:
13445   case 25:
13446   case 28:
13447   case 29:
13448   case 30:
13449   case 36:
13450   case 37:
13451   case 38:
13452     if (b1_facilities & B1_FACILITY_EC)
13453     {
13454       if (b1_facilities & B1_FACILITY_LOCAL)
13455         b = 30;
13456       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13457         b = 29;
13458       else
13459         b = 28;
13460     }
13461
13462     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13463       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13464        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13465     {
13466       if (b1_facilities & B1_FACILITY_LOCAL)
13467         b = 38;
13468       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13469         b = 37;
13470       else
13471         b = 36;
13472     }
13473
13474     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13475       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13476      || ((b1_facilities & B1_FACILITY_DTMFR)
13477       && ((b1_facilities & B1_FACILITY_MIXER)
13478        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13479      || ((b1_facilities & B1_FACILITY_DTMFX)
13480       && ((b1_facilities & B1_FACILITY_MIXER)
13481        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13482     {
13483       if (b1_facilities & B1_FACILITY_LOCAL)
13484         b = 24;
13485       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13486         b = 23;
13487       else
13488         b = 22;
13489     }
13490     else
13491     {
13492       if (b1_facilities & B1_FACILITY_LOCAL)
13493         b = 25;
13494       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13495         b = 20;
13496       else
13497         b = 9;
13498     }
13499     break;
13500
13501   case 31:
13502   case 32:
13503   case 33:
13504     if (b1_facilities & B1_FACILITY_LOCAL)
13505       b = 33;
13506     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13507       b = 32;
13508     else
13509       b = 31;
13510     break;
13511
13512   default:
13513     b = b1_resource;
13514   }
13515   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13516     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13517     (char   *)(FILE_), __LINE__,
13518     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13519   return (b);
13520 }
13521
13522
13523 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13524 {
13525   word removed_facilities;
13526
13527   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13528     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13529     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13530     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13531
13532   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13533   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13534
13535   if (removed_facilities & B1_FACILITY_EC)
13536     ec_clear_config (plci);
13537
13538
13539   if (removed_facilities & B1_FACILITY_DTMFR)
13540   {
13541     dtmf_rec_clear_config (plci);
13542     dtmf_parameter_clear_config (plci);
13543   }
13544   if (removed_facilities & B1_FACILITY_DTMFX)
13545     dtmf_send_clear_config (plci);
13546
13547
13548   if (removed_facilities & B1_FACILITY_MIXER)
13549     mixer_clear_config (plci);
13550
13551   if (removed_facilities & B1_FACILITY_VOICE)
13552     adv_voice_clear_config (plci);
13553   plci->B1_facilities = new_b1_facilities;
13554 }
13555
13556
13557 static void adjust_b_clear (PLCI   *plci)
13558 {
13559
13560   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13561     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13562     (char   *)(FILE_), __LINE__));
13563
13564   plci->adjust_b_restore = false;
13565 }
13566
13567
13568 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13569 {
13570   word Info;
13571   byte b1_resource;
13572   NCCI   * ncci_ptr;
13573     API_PARSE bp[2];
13574
13575   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13576     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13577
13578   Info = GOOD;
13579   switch (plci->adjust_b_state)
13580   {
13581   case ADJUST_B_START:
13582     if ((plci->adjust_b_parms_msg == NULL)
13583      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13584      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13585       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13586     {
13587       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13588         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13589       if (b1_resource == plci->B1_resource)
13590       {
13591         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13592         break;
13593       }
13594       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13595       {
13596         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13597           UnMapId (Id), (char   *)(FILE_), __LINE__,
13598           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13599         Info = _WRONG_STATE;
13600         break;
13601       }
13602     }
13603     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13604     {
13605
13606       mixer_prepare_switch (Id, plci);
13607
13608
13609       dtmf_prepare_switch (Id, plci);
13610       dtmf_parameter_prepare_switch (Id, plci);
13611
13612
13613       ec_prepare_switch (Id, plci);
13614
13615       adv_voice_prepare_switch (Id, plci);
13616     }
13617     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13618     Rc = OK;
13619   case ADJUST_B_SAVE_MIXER_1:
13620     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13621     {
13622
13623       Info = mixer_save_config (Id, plci, Rc);
13624       if ((Info != GOOD) || plci->internal_command)
13625         break;
13626
13627     }
13628     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13629     Rc = OK;
13630   case ADJUST_B_SAVE_DTMF_1:
13631     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13632     {
13633
13634       Info = dtmf_save_config (Id, plci, Rc);
13635       if ((Info != GOOD) || plci->internal_command)
13636         break;
13637
13638     }
13639     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13640   case ADJUST_B_REMOVE_L23_1:
13641     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13642      && plci->NL.Id && !plci->nl_remove_id)
13643     {
13644       plci->internal_command = plci->adjust_b_command;
13645       if (plci->adjust_b_ncci != 0)
13646       {
13647         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13648         while (ncci_ptr->data_pending)
13649         {
13650           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13651           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13652         }
13653         while (ncci_ptr->data_ack_pending)
13654           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13655       }
13656       nl_req_ncci (plci, REMOVE,
13657         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13658       send_req (plci);
13659       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13660       break;
13661     }
13662     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13663     Rc = OK;
13664   case ADJUST_B_REMOVE_L23_2:
13665     if ((Rc != OK) && (Rc != OK_FC))
13666     {
13667       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13668         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13669       Info = _WRONG_STATE;
13670       break;
13671     }
13672     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13673     {
13674       if (plci_nl_busy (plci))
13675       {
13676         plci->internal_command = plci->adjust_b_command;
13677         break;
13678       }
13679     }
13680     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13681     Rc = OK;
13682   case ADJUST_B_SAVE_EC_1:
13683     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13684     {
13685
13686       Info = ec_save_config (Id, plci, Rc);
13687       if ((Info != GOOD) || plci->internal_command)
13688         break;
13689
13690     }
13691     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13692     Rc = OK;
13693   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13694     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13695     {
13696
13697       Info = dtmf_parameter_save_config (Id, plci, Rc);
13698       if ((Info != GOOD) || plci->internal_command)
13699         break;
13700
13701     }
13702     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13703     Rc = OK;
13704   case ADJUST_B_SAVE_VOICE_1:
13705     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13706     {
13707       Info = adv_voice_save_config (Id, plci, Rc);
13708       if ((Info != GOOD) || plci->internal_command)
13709         break;
13710     }
13711     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13712   case ADJUST_B_SWITCH_L1_1:
13713     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13714     {
13715       if (plci->sig_req)
13716       {
13717         plci->internal_command = plci->adjust_b_command;
13718         break;
13719       }
13720       if (plci->adjust_b_parms_msg != NULL)
13721         api_load_msg (plci->adjust_b_parms_msg, bp);
13722       else
13723         api_load_msg (&plci->B_protocol, bp);
13724       Info = add_b1 (plci, bp,
13725         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13726         plci->adjust_b_facilities);
13727       if (Info != GOOD)
13728       {
13729         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13730           UnMapId (Id), (char   *)(FILE_), __LINE__,
13731           plci->B1_resource, plci->adjust_b_facilities));
13732         break;
13733       }
13734       plci->internal_command = plci->adjust_b_command;
13735       sig_req (plci, RESOURCES, 0);
13736       send_req (plci);
13737       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13738       break;
13739     }
13740     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13741     Rc = OK;
13742   case ADJUST_B_SWITCH_L1_2:
13743     if ((Rc != OK) && (Rc != OK_FC))
13744     {
13745       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13746         UnMapId (Id), (char   *)(FILE_), __LINE__,
13747         Rc, plci->B1_resource, plci->adjust_b_facilities));
13748       Info = _WRONG_STATE;
13749       break;
13750     }
13751     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13752     Rc = OK;
13753   case ADJUST_B_RESTORE_VOICE_1:
13754   case ADJUST_B_RESTORE_VOICE_2:
13755     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13756     {
13757       Info = adv_voice_restore_config (Id, plci, Rc);
13758       if ((Info != GOOD) || plci->internal_command)
13759         break;
13760     }
13761     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13762     Rc = OK;
13763   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13764   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13765     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13766     {
13767
13768       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13769       if ((Info != GOOD) || plci->internal_command)
13770         break;
13771
13772     }
13773     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13774     Rc = OK;
13775   case ADJUST_B_RESTORE_EC_1:
13776   case ADJUST_B_RESTORE_EC_2:
13777     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13778     {
13779
13780       Info = ec_restore_config (Id, plci, Rc);
13781       if ((Info != GOOD) || plci->internal_command)
13782         break;
13783
13784     }
13785     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13786   case ADJUST_B_ASSIGN_L23_1:
13787     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13788     {
13789       if (plci_nl_busy (plci))
13790       {
13791         plci->internal_command = plci->adjust_b_command;
13792         break;
13793       }
13794       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13795         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13796       if (plci->adjust_b_parms_msg != NULL)
13797         api_load_msg (plci->adjust_b_parms_msg, bp);
13798       else
13799         api_load_msg (&plci->B_protocol, bp);
13800       Info = add_b23 (plci, bp);
13801       if (Info != GOOD)
13802       {
13803         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13804           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13805         break;
13806       }
13807       plci->internal_command = plci->adjust_b_command;
13808       nl_req_ncci (plci, ASSIGN, 0);
13809       send_req (plci);
13810       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13811       break;
13812     }
13813     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13814     Rc = ASSIGN_OK;
13815   case ADJUST_B_ASSIGN_L23_2:
13816     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13817     {
13818       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13819         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13820       Info = _WRONG_STATE;
13821       break;
13822     }
13823     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13824     {
13825       if (Rc != ASSIGN_OK)
13826       {
13827         plci->internal_command = plci->adjust_b_command;
13828         break;
13829       }
13830     }
13831     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13832     {
13833       plci->adjust_b_restore = true;
13834       break;
13835     }
13836     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13837   case ADJUST_B_CONNECT_1:
13838     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13839     {
13840       plci->internal_command = plci->adjust_b_command;
13841       if (plci_nl_busy (plci))
13842         break;
13843       nl_req_ncci (plci, N_CONNECT, 0);
13844       send_req (plci);
13845       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13846       break;
13847     }
13848     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13849     Rc = OK;
13850   case ADJUST_B_CONNECT_2:
13851   case ADJUST_B_CONNECT_3:
13852   case ADJUST_B_CONNECT_4:
13853     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13854     {
13855       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13856         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13857       Info = _WRONG_STATE;
13858       break;
13859     }
13860     if (Rc == OK)
13861     {
13862       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13863       {
13864         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13865         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13866       }
13867       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13868         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13869       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13870         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13871     }
13872     else if (Rc == 0)
13873     {
13874       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13875         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13876       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13877         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13878     }
13879     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13880     {
13881       plci->internal_command = plci->adjust_b_command;
13882       break;
13883     }
13884     Rc = OK;
13885   case ADJUST_B_RESTORE_DTMF_1:
13886   case ADJUST_B_RESTORE_DTMF_2:
13887     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13888     {
13889
13890       Info = dtmf_restore_config (Id, plci, Rc);
13891       if ((Info != GOOD) || plci->internal_command)
13892         break;
13893
13894     }
13895     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13896     Rc = OK;
13897   case ADJUST_B_RESTORE_MIXER_1:
13898   case ADJUST_B_RESTORE_MIXER_2:
13899   case ADJUST_B_RESTORE_MIXER_3:
13900   case ADJUST_B_RESTORE_MIXER_4:
13901   case ADJUST_B_RESTORE_MIXER_5:
13902   case ADJUST_B_RESTORE_MIXER_6:
13903   case ADJUST_B_RESTORE_MIXER_7:
13904     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13905     {
13906
13907       Info = mixer_restore_config (Id, plci, Rc);
13908       if ((Info != GOOD) || plci->internal_command)
13909         break;
13910
13911     }
13912     plci->adjust_b_state = ADJUST_B_END;
13913   case ADJUST_B_END:
13914     break;
13915   }
13916   return (Info);
13917 }
13918
13919
13920 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13921 {
13922
13923   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13924     UnMapId (Id), (char   *)(FILE_), __LINE__,
13925     plci->B1_resource, b1_facilities));
13926
13927   plci->adjust_b_parms_msg = bp_msg;
13928   plci->adjust_b_facilities = b1_facilities;
13929   plci->adjust_b_command = internal_command;
13930   plci->adjust_b_ncci = (word)(Id >> 16);
13931   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13932     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13933   else
13934     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13935   plci->adjust_b_state = ADJUST_B_START;
13936   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13937     UnMapId (Id), (char   *)(FILE_), __LINE__,
13938     plci->B1_resource, b1_facilities));
13939 }
13940
13941
13942 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13943 {
13944   word internal_command;
13945
13946   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13947     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13948
13949   internal_command = plci->internal_command;
13950   plci->internal_command = 0;
13951   switch (internal_command)
13952   {
13953   default:
13954     plci->command = 0;
13955     if (plci->req_in != 0)
13956     {
13957       plci->internal_command = ADJUST_B_RESTORE_1;
13958       break;
13959     }
13960     Rc = OK;
13961   case ADJUST_B_RESTORE_1:
13962     if ((Rc != OK) && (Rc != OK_FC))
13963     {
13964       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13965         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13966     }
13967     plci->adjust_b_parms_msg = NULL;
13968     plci->adjust_b_facilities = plci->B1_facilities;
13969     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13970     plci->adjust_b_ncci = (word)(Id >> 16);
13971     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13972     plci->adjust_b_state = ADJUST_B_START;
13973     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13974       UnMapId (Id), (char   *)(FILE_), __LINE__));
13975   case ADJUST_B_RESTORE_2:
13976     if (adjust_b_process (Id, plci, Rc) != GOOD)
13977     {
13978       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13979         UnMapId (Id), (char   *)(FILE_), __LINE__));
13980     }
13981     if (plci->internal_command)
13982       break;
13983     break;
13984   }
13985 }
13986
13987
13988 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
13989 {
13990   word Info;
13991   word internal_command;
13992
13993   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13994     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13995
13996   Info = GOOD;
13997   internal_command = plci->internal_command;
13998   plci->internal_command = 0;
13999   switch (internal_command)
14000   {
14001   default:
14002     plci->command = 0;
14003     plci->adjust_b_parms_msg = NULL;
14004     plci->adjust_b_facilities = plci->B1_facilities;
14005     plci->adjust_b_command = RESET_B3_COMMAND_1;
14006     plci->adjust_b_ncci = (word)(Id >> 16);
14007     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14008     plci->adjust_b_state = ADJUST_B_START;
14009     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14010       UnMapId (Id), (char   *)(FILE_), __LINE__));
14011   case RESET_B3_COMMAND_1:
14012     Info = adjust_b_process (Id, plci, Rc);
14013     if (Info != GOOD)
14014     {
14015       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14016         UnMapId (Id), (char   *)(FILE_), __LINE__));
14017       break;
14018     }
14019     if (plci->internal_command)
14020       return;
14021     break;
14022   }
14023 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14024   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14025 }
14026
14027
14028 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14029 {
14030   word Info;
14031   word internal_command;
14032   byte esc_chi[3];
14033
14034   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14035     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14036
14037   Info = GOOD;
14038   internal_command = plci->internal_command;
14039   plci->internal_command = 0;
14040   switch (internal_command)
14041   {
14042   default:
14043     plci->command = 0;
14044     plci->adjust_b_parms_msg = &plci->saved_msg;
14045     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14046       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14047     else
14048       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14049     plci->adjust_b_command = SELECT_B_COMMAND_1;
14050     plci->adjust_b_ncci = (word)(Id >> 16);
14051     if (plci->saved_msg.parms[0].length == 0)
14052     {
14053       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14054         ADJUST_B_MODE_NO_RESOURCE;
14055     }
14056     else
14057     {
14058       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14059         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14060     }
14061     plci->adjust_b_state = ADJUST_B_START;
14062     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14063       UnMapId (Id), (char   *)(FILE_), __LINE__));
14064   case SELECT_B_COMMAND_1:
14065     Info = adjust_b_process (Id, plci, Rc);
14066     if (Info != GOOD)
14067     {
14068       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14069         UnMapId (Id), (char   *)(FILE_), __LINE__));
14070       break;
14071     }
14072     if (plci->internal_command)
14073       return;
14074     if (plci->tel == ADV_VOICE)
14075     {
14076       esc_chi[0] = 0x02;
14077       esc_chi[1] = 0x18;
14078       esc_chi[2] = plci->b_channel;
14079       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14080     }
14081     break;
14082   }
14083   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14084 }
14085
14086
14087 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14088 {
14089   word Info;
14090   word internal_command;
14091
14092   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14093     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14094
14095   Info = GOOD;
14096   internal_command = plci->internal_command;
14097   plci->internal_command = 0;
14098   switch (internal_command)
14099   {
14100   default:
14101     plci->command = 0;
14102   case FAX_CONNECT_ACK_COMMAND_1:
14103     if (plci_nl_busy (plci))
14104     {
14105       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14106       return;
14107     }
14108     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14109     plci->NData[0].P = plci->fax_connect_info_buffer;
14110     plci->NData[0].PLength = plci->fax_connect_info_length;
14111     plci->NL.X = plci->NData;
14112     plci->NL.ReqCh = 0;
14113     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14114     plci->adapter->request (&plci->NL);
14115     return;
14116   case FAX_CONNECT_ACK_COMMAND_2:
14117     if ((Rc != OK) && (Rc != OK_FC))
14118     {
14119       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14120         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14121       break;
14122     }
14123   }
14124   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14125    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14126   {
14127     if (plci->B3_prot == 4)
14128       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14129     else
14130       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14131     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14132   }
14133 }
14134
14135
14136 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14137 {
14138   word Info;
14139   word internal_command;
14140
14141   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14142     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14143
14144   Info = GOOD;
14145   internal_command = plci->internal_command;
14146   plci->internal_command = 0;
14147   switch (internal_command)
14148   {
14149   default:
14150     plci->command = 0;
14151   case FAX_EDATA_ACK_COMMAND_1:
14152     if (plci_nl_busy (plci))
14153     {
14154       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14155       return;
14156     }
14157     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14158     plci->NData[0].P = plci->fax_connect_info_buffer;
14159     plci->NData[0].PLength = plci->fax_edata_ack_length;
14160     plci->NL.X = plci->NData;
14161     plci->NL.ReqCh = 0;
14162     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14163     plci->adapter->request (&plci->NL);
14164     return;
14165   case FAX_EDATA_ACK_COMMAND_2:
14166     if ((Rc != OK) && (Rc != OK_FC))
14167     {
14168       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14169         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14170       break;
14171     }
14172   }
14173 }
14174
14175
14176 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14177 {
14178   word Info;
14179   word internal_command;
14180
14181   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14182     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14183
14184   Info = GOOD;
14185   internal_command = plci->internal_command;
14186   plci->internal_command = 0;
14187   switch (internal_command)
14188   {
14189   default:
14190     plci->command = 0;
14191   case FAX_CONNECT_INFO_COMMAND_1:
14192     if (plci_nl_busy (plci))
14193     {
14194       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14195       return;
14196     }
14197     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14198     plci->NData[0].P = plci->fax_connect_info_buffer;
14199     plci->NData[0].PLength = plci->fax_connect_info_length;
14200     plci->NL.X = plci->NData;
14201     plci->NL.ReqCh = 0;
14202     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14203     plci->adapter->request (&plci->NL);
14204     return;
14205   case FAX_CONNECT_INFO_COMMAND_2:
14206     if ((Rc != OK) && (Rc != OK_FC))
14207     {
14208       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14209         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14210       Info = _WRONG_STATE;
14211       break;
14212     }
14213     if (plci_nl_busy (plci))
14214     {
14215       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14216       return;
14217     }
14218     plci->command = _CONNECT_B3_R;
14219     nl_req_ncci (plci, N_CONNECT, 0);
14220     send_req (plci);
14221     return;
14222   }
14223   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14224 }
14225
14226
14227 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14228 {
14229   word Info;
14230   word internal_command;
14231
14232   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14233     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14234
14235   Info = GOOD;
14236   internal_command = plci->internal_command;
14237   plci->internal_command = 0;
14238   switch (internal_command)
14239   {
14240   default:
14241     plci->command = 0;
14242     plci->adjust_b_parms_msg = NULL;
14243     plci->adjust_b_facilities = plci->B1_facilities;
14244     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14245     plci->adjust_b_ncci = (word)(Id >> 16);
14246     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14247     plci->adjust_b_state = ADJUST_B_START;
14248     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14249       UnMapId (Id), (char   *)(FILE_), __LINE__));
14250   case FAX_ADJUST_B23_COMMAND_1:
14251     Info = adjust_b_process (Id, plci, Rc);
14252     if (Info != GOOD)
14253     {
14254       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14255         UnMapId (Id), (char   *)(FILE_), __LINE__));
14256       break;
14257     }
14258     if (plci->internal_command)
14259       return;
14260   case FAX_ADJUST_B23_COMMAND_2:
14261     if (plci_nl_busy (plci))
14262     {
14263       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14264       return;
14265     }
14266     plci->command = _CONNECT_B3_R;
14267     nl_req_ncci (plci, N_CONNECT, 0);
14268     send_req (plci);
14269     return;
14270   }
14271   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14272 }
14273
14274
14275 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14276 {
14277   word internal_command;
14278
14279   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14280     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14281
14282   internal_command = plci->internal_command;
14283   plci->internal_command = 0;
14284   switch (internal_command)
14285   {
14286   default:
14287     plci->command = 0;
14288     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14289     return;
14290   case FAX_DISCONNECT_COMMAND_1:
14291   case FAX_DISCONNECT_COMMAND_2:
14292   case FAX_DISCONNECT_COMMAND_3:
14293     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14294     {
14295       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14296         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14297       break;
14298     }
14299     if (Rc == OK)
14300     {
14301       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14302        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14303       {
14304         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14305       }
14306     }
14307     else if (Rc == 0)
14308     {
14309       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14310         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14311     }
14312     return;
14313   }
14314 }
14315
14316
14317
14318 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14319 {
14320   word Info;
14321   word internal_command;
14322
14323   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14324     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14325
14326   Info = GOOD;
14327   internal_command = plci->internal_command;
14328   plci->internal_command = 0;
14329   switch (internal_command)
14330   {
14331   default:
14332     plci->command = 0;
14333   case RTP_CONNECT_B3_REQ_COMMAND_1:
14334     if (plci_nl_busy (plci))
14335     {
14336       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14337       return;
14338     }
14339     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14340     nl_req_ncci (plci, N_CONNECT, 0);
14341     send_req (plci);
14342     return;
14343   case RTP_CONNECT_B3_REQ_COMMAND_2:
14344     if ((Rc != OK) && (Rc != OK_FC))
14345     {
14346       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14347         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14348       Info = _WRONG_STATE;
14349       break;
14350     }
14351     if (plci_nl_busy (plci))
14352     {
14353       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14354       return;
14355     }
14356     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14357     plci->NData[0].PLength = plci->internal_req_buffer[0];
14358     plci->NData[0].P = plci->internal_req_buffer + 1;
14359     plci->NL.X = plci->NData;
14360     plci->NL.ReqCh = 0;
14361     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14362     plci->adapter->request (&plci->NL);
14363     break;
14364   case RTP_CONNECT_B3_REQ_COMMAND_3:
14365     return;
14366   }
14367   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14368 }
14369
14370
14371 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14372 {
14373   word Info;
14374   word internal_command;
14375
14376   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14377     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14378
14379   Info = GOOD;
14380   internal_command = plci->internal_command;
14381   plci->internal_command = 0;
14382   switch (internal_command)
14383   {
14384   default:
14385     plci->command = 0;
14386   case RTP_CONNECT_B3_RES_COMMAND_1:
14387     if (plci_nl_busy (plci))
14388     {
14389       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14390       return;
14391     }
14392     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14393     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14394     send_req (plci);
14395     return;
14396   case RTP_CONNECT_B3_RES_COMMAND_2:
14397     if ((Rc != OK) && (Rc != OK_FC))
14398     {
14399       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14400         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14401       Info = _WRONG_STATE;
14402       break;
14403     }
14404     if (plci_nl_busy (plci))
14405     {
14406       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14407       return;
14408     }
14409     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14410     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14411     plci->NData[0].PLength = plci->internal_req_buffer[0];
14412     plci->NData[0].P = plci->internal_req_buffer + 1;
14413     plci->NL.X = plci->NData;
14414     plci->NL.ReqCh = 0;
14415     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14416     plci->adapter->request (&plci->NL);
14417     return;
14418   case RTP_CONNECT_B3_RES_COMMAND_3:
14419     return;
14420   }
14421 }
14422
14423
14424
14425 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14426 {
14427     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14428   word Info;
14429   word internal_command;
14430
14431   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14432     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14433
14434   Info = GOOD;
14435   internal_command = plci->internal_command;
14436   plci->internal_command = 0;
14437   switch (internal_command)
14438   {
14439   default:
14440     if (!plci->NL.Id)
14441       break;
14442     plci->command = 0;
14443     plci->adjust_b_parms_msg = NULL;
14444     plci->adjust_b_facilities = plci->B1_facilities;
14445     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14446     plci->adjust_b_ncci = (word)(Id >> 16);
14447     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14448     plci->adjust_b_state = ADJUST_B_START;
14449     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14450       UnMapId (Id), (char   *)(FILE_), __LINE__));
14451   case HOLD_SAVE_COMMAND_1:
14452     Info = adjust_b_process (Id, plci, Rc);
14453     if (Info != GOOD)
14454     {
14455       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14456         UnMapId (Id), (char   *)(FILE_), __LINE__));
14457       break;
14458     }
14459     if (plci->internal_command)
14460       return;
14461   }
14462   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14463 }
14464
14465
14466 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14467 {
14468     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14469   word Info;
14470   word internal_command;
14471
14472   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14473     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14474
14475   Info = GOOD;
14476   internal_command = plci->internal_command;
14477   plci->internal_command = 0;
14478   switch (internal_command)
14479   {
14480   default:
14481     plci->command = 0;
14482     plci->adjust_b_parms_msg = NULL;
14483     plci->adjust_b_facilities = plci->B1_facilities;
14484     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14485     plci->adjust_b_ncci = (word)(Id >> 16);
14486     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14487     plci->adjust_b_state = ADJUST_B_START;
14488     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14489       UnMapId (Id), (char   *)(FILE_), __LINE__));
14490   case RETRIEVE_RESTORE_COMMAND_1:
14491     Info = adjust_b_process (Id, plci, Rc);
14492     if (Info != GOOD)
14493     {
14494       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14495         UnMapId (Id), (char   *)(FILE_), __LINE__));
14496       break;
14497     }
14498     if (plci->internal_command)
14499       return;
14500   }
14501   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14502 }
14503
14504
14505 static void init_b1_config (PLCI   *plci)
14506 {
14507
14508   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14509     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14510     (char   *)(FILE_), __LINE__));
14511
14512   plci->B1_resource = 0;
14513   plci->B1_facilities = 0;
14514
14515   plci->li_bchannel_id = 0;
14516   mixer_clear_config (plci);
14517
14518
14519   ec_clear_config (plci);
14520
14521
14522   dtmf_rec_clear_config (plci);
14523   dtmf_send_clear_config (plci);
14524   dtmf_parameter_clear_config (plci);
14525
14526   adv_voice_clear_config (plci);
14527   adjust_b_clear (plci);
14528 }
14529
14530
14531 static void clear_b1_config (PLCI   *plci)
14532 {
14533
14534   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14535     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14536     (char   *)(FILE_), __LINE__));
14537
14538   adv_voice_clear_config (plci);
14539   adjust_b_clear (plci);
14540
14541   ec_clear_config (plci);
14542
14543
14544   dtmf_rec_clear_config (plci);
14545   dtmf_send_clear_config (plci);
14546   dtmf_parameter_clear_config (plci);
14547
14548
14549   if ((plci->li_bchannel_id != 0)
14550    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14551   {
14552     mixer_clear_config (plci);
14553     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14554     plci->li_bchannel_id = 0;
14555   }
14556
14557   plci->B1_resource = 0;
14558   plci->B1_facilities = 0;
14559 }
14560
14561
14562 /* -----------------------------------------------------------------
14563                 XON protocol local helpers
14564    ----------------------------------------------------------------- */
14565 static void channel_flow_control_remove (PLCI   * plci) {
14566   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14567   word i;
14568   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14569     if (a->ch_flow_plci[i] == plci->Id) {
14570       a->ch_flow_plci[i] = 0;
14571       a->ch_flow_control[i] = 0;
14572     }
14573   }
14574 }
14575
14576 static void channel_x_on (PLCI   * plci, byte ch) {
14577   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14578   if (a->ch_flow_control[ch] & N_XON_SENT) {
14579     a->ch_flow_control[ch] &= ~N_XON_SENT;
14580   }
14581 }
14582
14583 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14584   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14585   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14586     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14587     a->ch_flow_plci[ch] = plci->Id;
14588     a->ch_flow_control_pending++;
14589   }
14590 }
14591
14592 static void channel_request_xon (PLCI   * plci, byte ch) {
14593   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14594
14595   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14596     a->ch_flow_control[ch] |= N_XON_REQ;
14597     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14598     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14599   }
14600 }
14601
14602 static void channel_xmit_extended_xon (PLCI   * plci) {
14603   DIVA_CAPI_ADAPTER   * a;
14604   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14605   int i, one_requested = 0;
14606
14607   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14608     return;
14609   }
14610
14611   for (i = 0; i < max_ch; i++) {
14612     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14613         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14614         (plci->Id == a->ch_flow_plci[i])) {
14615       channel_request_xon (plci, (byte)i);
14616       one_requested = 1;
14617     }
14618   }
14619
14620   if (one_requested) {
14621     channel_xmit_xon (plci);
14622   }
14623 }
14624
14625 /*
14626   Try to xmit next X_ON
14627   */
14628 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14629   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14630   int i;
14631
14632   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14633     return (0);
14634   }
14635
14636   if (a->last_flow_control_ch >= max_ch) {
14637     a->last_flow_control_ch = 1;
14638   }
14639   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14640     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14641         (plci->Id == a->ch_flow_plci[i])) {
14642       a->last_flow_control_ch = i+1;
14643       return (i);
14644     }
14645   }
14646
14647   for (i = 1; i < a->last_flow_control_ch; i++) {
14648     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649         (plci->Id == a->ch_flow_plci[i])) {
14650       a->last_flow_control_ch = i+1;
14651       return (i);
14652     }
14653   }
14654
14655   return (0);
14656 }
14657
14658 static void channel_xmit_xon (PLCI   * plci) {
14659   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14660   byte ch;
14661
14662   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14663     return;
14664   }
14665   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14666     return;
14667   }
14668   a->ch_flow_control[ch] &= ~N_XON_REQ;
14669   a->ch_flow_control[ch] |= N_XON_SENT;
14670
14671   plci->NL.Req = plci->nl_req = (byte)N_XON;
14672   plci->NL.ReqCh         = ch;
14673   plci->NL.X             = plci->NData;
14674   plci->NL.XNum          = 1;
14675   plci->NData[0].P       = &plci->RBuffer[0];
14676   plci->NData[0].PLength = 0;
14677
14678   plci->adapter->request(&plci->NL);
14679 }
14680
14681 static int channel_can_xon (PLCI   * plci, byte ch) {
14682   APPL   * APPLptr;
14683   DIVA_CAPI_ADAPTER   * a;
14684   word NCCIcode;
14685   dword count;
14686   word Num;
14687   word i;
14688
14689   APPLptr = plci->appl;
14690   a = plci->adapter;
14691
14692   if (!APPLptr)
14693     return (0);
14694
14695   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14696
14697                 /* count all buffers within the Application pool    */
14698                 /* belonging to the same NCCI. XON if a first is    */
14699                 /* used.                                            */
14700   count = 0;
14701   Num = 0xffff;
14702   for(i=0; i<APPLptr->MaxBuffer; i++) {
14703     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14704     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14705   }
14706   if ((count > 2) || (Num == 0xffff)) {
14707     return (0);
14708   }
14709   return (1);
14710 }
14711
14712
14713 /*------------------------------------------------------------------*/
14714
14715 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14716 {
14717   return 1;
14718 }
14719
14720
14721
14722 /**********************************************************************************/
14723 /* function groups the listening applications according to the CIP mask and the   */
14724 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14725 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14726 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14727 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14728 /* OS specific part (per adapter).                                                */
14729 /**********************************************************************************/
14730 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14731 {
14732   word i,j,k,busy,group_found;
14733   dword info_mask_group[MAX_CIP_TYPES];
14734   dword cip_mask_group[MAX_CIP_TYPES];
14735   word appl_number_group_type[MAX_APPL];
14736   PLCI   *auxplci;
14737
14738   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14739
14740   if(!a->group_optimization_enabled)
14741   {
14742     dbug(1,dprintf("No group optimization"));
14743     return;
14744   }
14745
14746   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14747
14748   for(i=0;i<MAX_CIP_TYPES;i++)
14749   {
14750     info_mask_group[i] = 0;
14751     cip_mask_group [i] = 0;
14752   }
14753   for(i=0;i<MAX_APPL;i++)
14754   {
14755     appl_number_group_type[i] = 0;
14756   }
14757   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14758   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14759     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14760     {
14761       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14762       return; /* allow good application unfiltered access */
14763     }
14764   }
14765   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14766   {
14767     if(application[i].Id && a->CIP_Mask[i] )
14768     {
14769       for(k=0,busy=false; k<a->max_plci; k++)
14770       {
14771         if(a->plci[k].Id) 
14772         {
14773           auxplci = &a->plci[k];
14774           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14775           {
14776             busy = true;
14777             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14778           }
14779           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14780           {
14781             busy = true;
14782             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14783           }
14784         }
14785       }
14786
14787       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14788       {
14789         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14790         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14791           appl_number_group_type[i] = MAX_CIP_TYPES;
14792           group_found=true;
14793           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14794         }
14795         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14796         {                                      /* is group already present ?                  */
14797           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14798           group_found=true;
14799           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]));
14800         }
14801         else if(!info_mask_group[j])
14802         {                                      /* establish a new group                       */
14803           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14804           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14805           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14806           group_found=true;
14807           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]));
14808         }
14809       }
14810     }
14811   }
14812         
14813   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14814   {
14815     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14816     {
14817       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14818       {
14819         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14820       }
14821       else
14822       {
14823         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14824         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14825         {
14826           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14827           {
14828             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14829             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14830             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14831           }
14832         }
14833       }
14834     }
14835     else                                                 /* application should not get a call */
14836     {
14837       clear_group_ind_mask_bit (plci, i);
14838     }
14839   }
14840
14841 }
14842
14843
14844
14845 /* OS notifies the driver about a application Capi_Register */
14846 word CapiRegister(word id)
14847 {
14848   word i,j,appls_found;
14849
14850   PLCI   *plci;
14851   DIVA_CAPI_ADAPTER   *a;
14852
14853   for(i=0,appls_found=0; i<max_appl; i++)
14854   {
14855     if( application[i].Id && (application[i].Id!=id) )
14856     {
14857       appls_found++;                       /* an application has been found */
14858     }
14859   }
14860
14861   if(appls_found) return true;
14862   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14863   {
14864     a = &adapter[i];
14865     if(a->request)
14866     {
14867       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14868       {
14869         if(!appls_found)           /* first application does a capi register   */
14870         {
14871           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14872           {
14873             plci = &a->plci[j-1];
14874             plci->command = 0;
14875             add_p(plci,OAD,"\x01\xfd");
14876             add_p(plci,CAI,"\x01\x80");
14877             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14878             add_p(plci,SHIFT|6,NULL);
14879             add_p(plci,SIN,"\x02\x00\x00");
14880             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14881             sig_req(plci,ASSIGN,DSIG_ID);
14882             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14883             sig_req(plci,SIG_CTRL,0);
14884             send_req(plci);
14885           }
14886         }
14887       }
14888     }
14889   }
14890   return false;
14891 }
14892
14893 /*------------------------------------------------------------------*/
14894
14895 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14896
14897 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14898 {
14899  word i;
14900  /* Format of vswitch_t:
14901  0 byte length
14902  1 byte VSWITCHIE
14903  2 byte VSWITCH_REQ/VSWITCH_IND
14904  3 byte reserved
14905  4 word VSwitchcommand
14906  6 word returnerror
14907  8... Params
14908  */
14909  if(!plci ||
14910   !plci->appl ||
14911   !plci->State ||
14912   plci->Sig.Ind==NCR_FACILITY
14913   )
14914   return;
14915  
14916  for(i=0;i<MAX_MULTI_IE;i++)
14917  {
14918         if(!parms[i][0]) continue;
14919   if(parms[i][0]<7)
14920   {
14921    parms[i][0]=0; /* kill it */
14922    continue;
14923   }
14924   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14925   switch(parms[i][4])
14926   {
14927   case VSJOIN:
14928    if(!plci->relatedPTYPLCI ||
14929     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14930    { /* Error */
14931     break;
14932    }
14933    /* remember all necessary informations */
14934    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14935    {
14936     break;
14937    }
14938    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14939    {   /* first indication after ECT-Request on Consultation Call */
14940     plci->vswitchstate=parms[i][9];
14941     parms[i][9]=2; /* State */
14942     /* now ask first Call to join */
14943    }
14944    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14945    { /* Answer of VSWITCH_REQ from first Call */
14946     plci->vswitchstate=parms[i][9];
14947     /* tell consultation call to join
14948     and the protocol capabilities of the first call */
14949    }
14950    else
14951    { /* Error */
14952     break;
14953    }    
14954    plci->vsprot=parms[i][10]; /* protocol */
14955    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14956    /* send join request to related PLCI */
14957    parms[i][1]=VSWITCHIE;
14958    parms[i][2]=VSWITCH_REQ;
14959    
14960    plci->relatedPTYPLCI->command = 0;
14961    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14962    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14963    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14964    send_req(plci->relatedPTYPLCI);
14965    break;
14966   case VSTRANSPORT:
14967   default:
14968    if(plci->relatedPTYPLCI &&
14969     plci->vswitchstate==3 &&
14970     plci->relatedPTYPLCI->vswitchstate==3)
14971    {
14972     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14973     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14974     send_req(plci->relatedPTYPLCI);
14975    }
14976    break;
14977   }  
14978   parms[i][0]=0; /* kill it */
14979  }
14980 }
14981
14982
14983 /*------------------------------------------------------------------*/
14984
14985 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
14986   ENTITY e;
14987   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14988
14989   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14990     return (-1);
14991   }
14992
14993   pReq->xdi_dma_descriptor_operation.Req = 0;
14994   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14995
14996   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14997   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14998   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14999   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15000
15001   e.user[0] = plci->adapter->Id - 1;
15002   plci->adapter->request((ENTITY*)pReq);
15003
15004   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15005       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15006       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15007     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15008     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15009          plci->adapter->Id,
15010          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15011          *dma_magic));
15012     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15013   } else {
15014     dbug(1,dprintf("dma_alloc failed"));
15015     return (-1);
15016   }
15017 }
15018
15019 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15020   ENTITY e;
15021   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15022
15023   if (nr < 0) {
15024     return;
15025   }
15026
15027   pReq->xdi_dma_descriptor_operation.Req = 0;
15028   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15029
15030   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15031   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15032   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15033   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15034
15035   e.user[0] = plci->adapter->Id - 1;
15036   plci->adapter->request((ENTITY*)pReq);
15037
15038   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15039     dbug(1,dprintf("dma_free(%d)", nr));
15040   } else {
15041     dbug(1,dprintf("dma_free failed (%d)", nr));
15042   }
15043 }
15044
15045 /*------------------------------------------------------------------*/