vserver 1.9.5.x5
[linux-2.6.git] / drivers / isdn / hardware / eicon / message.c
1
2 /*
3  *
4   Copyright (c) Eicon Networks, 2002.
5  *
6   This source file is supplied for the use with
7   Eicon Networks range of DIVA Server Adapters.
8  *
9   Eicon File Revision :    2.1
10  *
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2, or (at your option)
14   any later version.
15  *
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19   See the GNU General Public License for more details.
20  *
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27
28
29
30
31 #include "platform.h"
32 #include "di_defs.h"
33 #include "pc.h"
34 #include "capi20.h"
35 #include "divacapi.h"
36 #include "mdm_msg.h"
37 #include "divasync.h"
38
39
40
41 #define FILE_ "MESSAGE.C"
42 #define dprintf
43
44
45
46
47
48
49
50
51
52 /*------------------------------------------------------------------*/
53 /* This is options supported for all adapters that are server by    */
54 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
55 /* and it is not necessary to save it separate for every adapter    */
56 /* Macrose defined here have only local meaning                     */
57 /*------------------------------------------------------------------*/
58 static dword diva_xdi_extended_features = 0;
59
60 #define DIVA_CAPI_USE_CMA                 0x00000001
61 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
62 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
63 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
64
65 /*
66   CAPI can request to process all return codes self only if:
67   protocol code supports this && xdi supports this
68  */
69 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
70
71 /*------------------------------------------------------------------*/
72 /* local function prototypes                                        */
73 /*------------------------------------------------------------------*/
74
75 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
76 static void set_group_ind_mask (PLCI   *plci);
77 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
78 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
79 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
80 word CapiRelease(word);
81 word CapiRegister(word);
82 word api_put(APPL   *, CAPI_MSG   *);
83 static word api_parse(byte   *, word, byte *, API_PARSE *);
84 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
85 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
86
87 word api_remove_start(void);
88 void api_remove_complete(void);
89
90 static void plci_remove(PLCI   *);
91 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
92 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
93
94 void   callback(ENTITY   *);
95
96 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
97 static void data_rc(PLCI   *, byte);
98 static void data_ack(PLCI   *, byte);
99 static void sig_ind(PLCI   *);
100 static void SendInfo(PLCI   *, dword, byte   * *, byte);
101 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
102 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
103
104 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
105
106 static void nl_ind(PLCI   *);
107
108 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
132
133 static word get_plci(DIVA_CAPI_ADAPTER   *);
134 static void add_p(PLCI   *, byte, byte   *);
135 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
137 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
138 static void add_d(PLCI   *, word, byte   *);
139 static void add_ai(PLCI   *, API_PARSE *);
140 static word add_b1(PLCI   *, API_PARSE *, word, word);
141 static word add_b23(PLCI   *, API_PARSE *);
142 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
143 static void sig_req(PLCI   *, byte, byte);
144 static void nl_req_ncci(PLCI   *, byte, byte);
145 static void send_req(PLCI   *);
146 static void send_data(PLCI   *);
147 static word plci_remove_check(PLCI   *);
148 static void listen_check(DIVA_CAPI_ADAPTER   *);
149 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
150 static byte getChannel(API_PARSE *);
151 static void IndParse(PLCI   *, word *, byte   **, byte);
152 static byte ie_compare(byte   *, byte *);
153 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
154 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
155
156 /*
157   XON protocol helpers
158   */
159 static void channel_flow_control_remove (PLCI   * plci);
160 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
161 static void channel_x_on (PLCI   * plci, byte ch);
162 static void channel_request_xon (PLCI   * plci, byte ch);
163 static void channel_xmit_xon (PLCI   * plci);
164 static int channel_can_xon (PLCI   * plci, byte ch);
165 static void channel_xmit_extended_xon (PLCI   * plci);
166
167 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
168 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
169 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
170 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
171 static void VoiceChannelOff(PLCI   *plci);
172 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
173 static void adv_voice_clear_config (PLCI   *plci);
174
175 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
176 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
177 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
178 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
179 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
180 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
181 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
182 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
187 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
188 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
189 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
190 static void init_b1_config (PLCI   *plci);
191 static void clear_b1_config (PLCI   *plci);
192
193 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
194 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
195 static void dtmf_confirmation (dword Id, PLCI   *plci);
196 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
197 static void dtmf_parameter_write (PLCI   *plci);
198
199
200 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
201 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
202 static void mixer_clear_config (PLCI   *plci);
203 static void mixer_notify_update (PLCI   *plci, byte others);
204 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
205 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
206 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
207 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
209 static void mixer_remove (PLCI   *plci);
210
211
212 static void ec_command (dword Id, PLCI   *plci, byte Rc);
213 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
214 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
215
216
217 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
218 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
219
220
221 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
222 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
223
224 /*------------------------------------------------------------------*/
225 /* external function prototypes                                     */
226 /*------------------------------------------------------------------*/
227
228 extern byte MapController (byte);
229 extern byte UnMapController (byte);
230 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
231 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
232
233 void   sendf(APPL   *, word, dword, word, byte *, ...);
234 void   * TransmitBufferSet(APPL   * appl, dword ref);
235 void   * TransmitBufferGet(APPL   * appl, void   * p);
236 void TransmitBufferFree(APPL   * appl, void   * p);
237 void   * ReceiveBufferGet(APPL   * appl, int Num);
238
239 int fax_head_line_time (char *buffer);
240
241
242 /*------------------------------------------------------------------*/
243 /* Global data definitions                                          */
244 /*------------------------------------------------------------------*/
245 extern byte max_adapter;
246 extern byte max_appl;
247 extern DIVA_CAPI_ADAPTER   * adapter;
248 extern APPL   * application;
249
250
251
252
253
254
255
256 static byte remove_started = FALSE;
257 static PLCI dummy_plci;
258
259
260 static struct _ftable {
261   word command;
262   byte * format;
263   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
264 } ftable[] = {
265   {_DATA_B3_R,                          "dwww",         data_b3_req},
266   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
267   {_INFO_R,                             "ss",           info_req},
268   {_INFO_I|RESPONSE,                    "",             info_res},
269   {_CONNECT_R,                          "wsssssssss",   connect_req},
270   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
271   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
272   {_DISCONNECT_R,                       "s",            disconnect_req},
273   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
274   {_LISTEN_R,                           "dddss",        listen_req},
275   {_ALERT_R,                            "s",            alert_req},
276   {_FACILITY_R,                         "ws",           facility_req},
277   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
278   {_CONNECT_B3_R,                       "s",            connect_b3_req},
279   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
280   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
281   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
282   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
283   {_RESET_B3_R,                         "s",            reset_b3_req},
284   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
286   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
287   {_SELECT_B_REQ,                       "s",            select_b_req},
288   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
289   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
290   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
291 };
292
293 static byte * cip_bc[29][2] = {
294   { "",                     ""                     }, /* 0 */
295   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
296   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
297   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
298   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
299   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
300   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
301   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
302   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
303   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
304   { "",                     ""                     }, /* 10 */
305   { "",                     ""                     }, /* 11 */
306   { "",                     ""                     }, /* 12 */
307   { "",                     ""                     }, /* 13 */
308   { "",                     ""                     }, /* 14 */
309   { "",                     ""                     }, /* 15 */
310
311   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
312   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
320   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
322   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
323   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
324 };
325
326 static byte * cip_hlc[29] = {
327   "",                           /* 0 */
328   "",                           /* 1 */
329   "",                           /* 2 */
330   "",                           /* 3 */
331   "",                           /* 4 */
332   "",                           /* 5 */
333   "",                           /* 6 */
334   "",                           /* 7 */
335   "",                           /* 8 */
336   "",                           /* 9 */
337   "",                           /* 10 */
338   "",                           /* 11 */
339   "",                           /* 12 */
340   "",                           /* 13 */
341   "",                           /* 14 */
342   "",                           /* 15 */
343
344   "\x02\x91\x81",               /* 16 */
345   "\x02\x91\x84",               /* 17 */
346   "\x02\x91\xa1",               /* 18 */
347   "\x02\x91\xa4",               /* 19 */
348   "\x02\x91\xa8",               /* 20 */
349   "\x02\x91\xb1",               /* 21 */
350   "\x02\x91\xb2",               /* 22 */
351   "\x02\x91\xb5",               /* 23 */
352   "\x02\x91\xb8",               /* 24 */
353   "\x02\x91\xc1",               /* 25 */
354   "\x02\x91\x81",               /* 26 */
355   "\x03\x91\xe0\x01",           /* 27 */
356   "\x03\x91\xe0\x02"            /* 28 */
357 };
358
359 /*------------------------------------------------------------------*/
360
361 #define V120_HEADER_LENGTH 1
362 #define V120_HEADER_EXTEND_BIT  0x80
363 #define V120_HEADER_BREAK_BIT   0x40
364 #define V120_HEADER_C1_BIT      0x04
365 #define V120_HEADER_C2_BIT      0x08
366 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
367
368 static byte v120_default_header[] =
369 {
370
371   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
372
373 };
374
375 static byte v120_break_header[] =
376 {
377
378   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
379
380 };
381
382
383 /*------------------------------------------------------------------*/
384 /* API_PUT function                                                 */
385 /*------------------------------------------------------------------*/
386
387 word api_put(APPL   * appl, CAPI_MSG   * msg)
388 {
389   word i, j, k, l, n;
390   word ret;
391   byte c;
392   byte controller;
393   DIVA_CAPI_ADAPTER   * a;
394   PLCI   * plci;
395   NCCI   * ncci_ptr;
396   word ncci;
397   CAPI_MSG   *m;
398     API_PARSE msg_parms[MAX_MSG_PARMS+1];
399
400   if (msg->header.length < sizeof (msg->header) ||
401       msg->header.length > MAX_MSG_SIZE) {
402     dbug(1,dprintf("bad len"));
403     return _BAD_MSG;
404   }
405
406   controller = (byte)((msg->header.controller &0x7f)-1);
407
408   /* controller starts with 0 up to (max_adapter - 1) */
409   if ( controller >= max_adapter )
410   {
411     dbug(1,dprintf("invalid ctrl"));
412     return _BAD_MSG;
413   }
414   
415   a = &adapter[controller];
416   plci = NULL;
417   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
418   {
419     dbug(1,dprintf("plci=%x",msg->header.plci));
420     plci = &a->plci[msg->header.plci-1];
421     ncci = GET_WORD(&msg->header.ncci);
422     if (plci->Id
423      && (plci->appl
424       || (plci->State == INC_CON_PENDING)
425       || (plci->State == INC_CON_ALERT)
426       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
427      && ((ncci == 0)
428       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
429       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
430     {
431       i = plci->msg_in_read_pos;
432       j = plci->msg_in_write_pos;
433       if (j >= i)
434       {
435         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
436           i += MSG_IN_QUEUE_SIZE - j;
437         else
438           j = 0;
439       }
440       else
441       {
442
443         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
444
445         if (i > MSG_IN_QUEUE_SIZE - n)
446           i = MSG_IN_QUEUE_SIZE - n + 1;
447         i -= j;
448       }
449
450       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
451
452       {
453         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
454           msg->header.length, plci->msg_in_write_pos,
455           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
456
457         return _QUEUE_FULL;
458       }
459       c = FALSE;
460       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
461        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
462       {
463         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
464           c = TRUE;
465       }
466       if (msg->header.command == _DATA_B3_R)
467       {
468         if (msg->header.length < 20)
469         {
470           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
471           return _BAD_MSG;
472         }
473         ncci_ptr = &(a->ncci[ncci]);
474         n = ncci_ptr->data_pending;
475         l = ncci_ptr->data_ack_pending;
476         k = plci->msg_in_read_pos;
477         while (k != plci->msg_in_write_pos)
478         {
479           if (k == plci->msg_in_wrap_pos)
480             k = 0;
481           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
482            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
483           {
484             n++;
485             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
486               l++;
487           }
488
489           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
490             MSG_IN_OVERHEAD + 3) & 0xfffc;
491
492         }
493         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
494         {
495           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
496                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
497
498           return _QUEUE_FULL;
499         }
500         if (plci->req_in || plci->internal_command)
501         {
502           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
503            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
504           {
505             dbug(0,dprintf("Q-FULL3(requeue)"));
506
507             return _QUEUE_FULL;
508           }
509           c = TRUE;
510         }
511       }
512       else
513       {
514         if (plci->req_in || plci->internal_command)
515           c = TRUE;
516         else
517         {
518           plci->command = msg->header.command;
519           plci->number = msg->header.number;
520         }
521       }
522       if (c)
523       {
524         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
525           msg->header.command, plci->req_in, plci->internal_command,
526           msg->header.length, plci->msg_in_write_pos,
527           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
528         if (j == 0)
529           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
530         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
531         for (i = 0; i < msg->header.length; i++)
532           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
533         if (m->header.command == _DATA_B3_R)
534         {
535
536           m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
537
538         }
539
540         j = (j + 3) & 0xfffc;
541
542         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
543         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
544         return 0;
545       }
546     }
547     else
548     {
549       plci = NULL;
550     }
551   }
552   dbug(1,dprintf("com=%x",msg->header.command));
553
554   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
555   for(i=0, ret = _BAD_MSG;
556       i<(sizeof(ftable)/sizeof(struct _ftable));
557       i++) {
558
559     if(ftable[i].command==msg->header.command) {
560       /* break loop if the message is correct, otherwise continue scan  */
561       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
562       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
563         ret = 0;
564         break;
565       }
566       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
567     }
568   }
569   if(ret) {
570     dbug(1,dprintf("BAD_MSG"));
571     if(plci) plci->command = 0;
572     return ret;
573   }
574
575
576   c = ftable[i].function(GET_DWORD(&msg->header.controller),
577                          msg->header.number,
578                          a,
579                          plci,
580                          appl,
581                          msg_parms);
582
583   channel_xmit_extended_xon (plci);
584
585   if(c==1) send_req(plci);
586   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
587   if(plci && !plci->req_in) plci->command = 0;
588   return 0;
589 }
590
591
592 /*------------------------------------------------------------------*/
593 /* api_parse function, check the format of api messages             */
594 /*------------------------------------------------------------------*/
595
596 word api_parse(byte   * msg, word length, byte * format, API_PARSE * parms)
597 {
598   word i;
599   word p;
600
601   for(i=0,p=0; format[i]; i++) {
602     if(parms)
603     {
604       parms[i].info = &msg[p];
605     }
606     switch(format[i]) {
607     case 'b':
608       p +=1;
609       break;
610     case 'w':
611       p +=2;
612       break;
613     case 'd':
614       p +=4;
615       break;
616     case 's':
617       if(msg[p]==0xff) {
618         parms[i].info +=2;
619         parms[i].length = msg[p+1] + (msg[p+2]<<8);
620         p +=(parms[i].length +3);
621       }
622       else {
623         parms[i].length = msg[p];
624         p +=(parms[i].length +1);
625       }
626       break;
627     }
628
629     if(p>length) return TRUE;
630   }
631   if(parms) parms[i].info = NULL;
632   return FALSE;
633 }
634
635 void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
636 {
637   word i, j, n = 0;
638   byte   *p;
639
640   p = out->info;
641   for (i = 0; format[i] != '\0'; i++)
642   {
643     out->parms[i].info = p;
644     out->parms[i].length = in[i].length;
645     switch (format[i])
646     {
647     case 'b':
648       n = 1;
649       break;
650     case 'w':
651       n = 2;
652       break;
653     case 'd':
654       n = 4;
655       break;
656     case 's':
657       n = in[i].length + 1;
658       break;
659     }
660     for (j = 0; j < n; j++)
661       *(p++) = in[i].info[j];
662   }
663   out->parms[i].info = NULL;
664   out->parms[i].length = 0;
665 }
666
667 void api_load_msg(API_SAVE   *in, API_PARSE   *out)
668 {
669   word i;
670
671   i = 0;
672   do
673   {
674     out[i].info = in->parms[i].info;
675     out[i].length = in->parms[i].length;
676   } while (in->parms[i++].info);
677 }
678
679
680 /*------------------------------------------------------------------*/
681 /* CAPI remove function                                             */
682 /*------------------------------------------------------------------*/
683
684 word api_remove_start(void)
685 {
686   word i;
687   word j;
688
689   if(!remove_started) {
690     remove_started = TRUE;
691     for(i=0;i<max_adapter;i++) {
692       if(adapter[i].request) {
693         for(j=0;j<adapter[i].max_plci;j++) {
694           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
695         }
696       }
697     }
698     return 1;
699   }
700   else {
701     for(i=0;i<max_adapter;i++) {
702       if(adapter[i].request) {
703         for(j=0;j<adapter[i].max_plci;j++) {
704           if(adapter[i].plci[j].Sig.Id) return 1;
705         }
706       }
707     }
708   }
709   api_remove_complete();
710   return 0;
711 }
712
713
714 /*------------------------------------------------------------------*/
715 /* internal command queue                                           */
716 /*------------------------------------------------------------------*/
717
718 static void init_internal_command_queue (PLCI   *plci)
719 {
720   word i;
721
722   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
723     (char   *)(FILE_), __LINE__));
724
725   plci->internal_command = 0;
726   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
727     plci->internal_command_queue[i] = NULL;
728 }
729
730
731 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
732 {
733   word i;
734
735   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
736     UnMapId (Id), (char   *)(FILE_), __LINE__));
737
738   if (plci->internal_command == 0)
739   {
740     plci->internal_command_queue[0] = command_function;
741     (* command_function)(Id, plci, OK);
742   }
743   else
744   {
745     i = 1;
746     while (plci->internal_command_queue[i] != 0)
747       i++;
748     plci->internal_command_queue[i] = command_function;
749   }
750 }
751
752
753 static void next_internal_command (dword Id, PLCI   *plci)
754 {
755   word i;
756
757   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
758     UnMapId (Id), (char   *)(FILE_), __LINE__));
759
760   plci->internal_command = 0;
761   plci->internal_command_queue[0] = NULL;
762   while (plci->internal_command_queue[1] != 0)
763   {
764     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
765       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
766     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
767     (*(plci->internal_command_queue[0]))(Id, plci, OK);
768     if (plci->internal_command != 0)
769       return;
770     plci->internal_command_queue[0] = NULL;
771   }
772 }
773
774
775 /*------------------------------------------------------------------*/
776 /* NCCI allocate/remove function                                    */
777 /*------------------------------------------------------------------*/
778
779 static dword ncci_mapping_bug = 0;
780
781 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
782 {
783   DIVA_CAPI_ADAPTER   *a;
784   word ncci, i, j, k;
785
786   a = plci->adapter;
787   if (!ch || a->ch_ncci[ch])
788   {
789     ncci_mapping_bug++;
790     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
791       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
792     ncci = ch;
793   }
794   else
795   {
796     if (force_ncci)
797       ncci = force_ncci;
798     else
799     {
800       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
801         ncci = ch;
802       else
803       {
804         ncci = 1;
805         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
806           ncci++;
807         if (ncci == MAX_NCCI+1)
808         {
809           ncci_mapping_bug++;
810           i = 1;
811           do
812           {
813             j = 1;
814             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
815               j++;
816             k = j;
817             if (j < MAX_NCCI+1)
818             {
819               do
820               {
821                 j++;
822               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
823             }
824           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
825           if (i < MAX_NL_CHANNEL+1)
826           {
827             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
828               ncci_mapping_bug, ch, force_ncci, i, k, j));
829           }
830           else
831           {
832             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
833               ncci_mapping_bug, ch, force_ncci));
834           }
835           ncci = ch;
836         }
837       }
838       a->ncci_plci[ncci] = plci->Id;
839       a->ncci_state[ncci] = IDLE;
840       if (!plci->ncci_ring_list)
841         plci->ncci_ring_list = ncci;
842       else
843         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
844       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
845     }
846     a->ncci_ch[ncci] = ch;
847     a->ch_ncci[ch] = (byte) ncci;
848     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
849       ncci_mapping_bug, ch, force_ncci, ch, ncci));
850   }
851   return (ncci);
852 }
853
854
855 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
856 {
857   DIVA_CAPI_ADAPTER   *a;
858   APPL   *appl;
859   word i, ncci_code;
860   dword Id;
861
862   a = plci->adapter;
863   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
864   if (ncci)
865   {
866     if (a->ncci_plci[ncci] == plci->Id)
867     {
868       if (!plci->appl)
869       {
870         ncci_mapping_bug++;
871         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
872           ncci_mapping_bug, Id));
873       }
874       else
875       {
876         appl = plci->appl;
877         ncci_code = ncci | (((word) a->Id) << 8);
878         for (i = 0; i < appl->MaxBuffer; i++)
879         {
880           if ((appl->DataNCCI[i] == ncci_code)
881            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
882           {
883             appl->DataNCCI[i] = 0;
884           }
885         }
886       }
887     }
888   }
889   else
890   {
891     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
892     {
893       if (a->ncci_plci[ncci] == plci->Id)
894       {
895         if (!plci->appl)
896         {
897           ncci_mapping_bug++;
898           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
899             ncci_mapping_bug, Id));
900         }
901         else
902         {
903           appl = plci->appl;
904           ncci_code = ncci | (((word) a->Id) << 8);
905           for (i = 0; i < appl->MaxBuffer; i++)
906           {
907             if ((appl->DataNCCI[i] == ncci_code)
908              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
909             {
910               appl->DataNCCI[i] = 0;
911             }
912           }
913         }
914       }
915     }
916   }
917 }
918
919
920 static void cleanup_ncci_data (PLCI   *plci, word ncci)
921 {
922   NCCI   *ncci_ptr;
923
924   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
925   {
926     ncci_ptr = &(plci->adapter->ncci[ncci]);
927     if (plci->appl)
928     {
929       while (ncci_ptr->data_pending != 0)
930       {
931         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
932           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
933         (ncci_ptr->data_out)++;
934         if (ncci_ptr->data_out == MAX_DATA_B3)
935           ncci_ptr->data_out = 0;
936         (ncci_ptr->data_pending)--;
937       }
938     }
939     ncci_ptr->data_out = 0;
940     ncci_ptr->data_pending = 0;
941     ncci_ptr->data_ack_out = 0;
942     ncci_ptr->data_ack_pending = 0;
943   }
944 }
945
946
947 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
948 {
949   DIVA_CAPI_ADAPTER   *a;
950   dword Id;
951   word i;
952
953   a = plci->adapter;
954   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
955   if (!preserve_ncci)
956     ncci_free_receive_buffers (plci, ncci);
957   if (ncci)
958   {
959     if (a->ncci_plci[ncci] != plci->Id)
960     {
961       ncci_mapping_bug++;
962       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
963         ncci_mapping_bug, Id, preserve_ncci));
964     }
965     else
966     {
967       cleanup_ncci_data (plci, ncci);
968       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
969         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
970       a->ch_ncci[a->ncci_ch[ncci]] = 0;
971       if (!preserve_ncci)
972       {
973         a->ncci_ch[ncci] = 0;
974         a->ncci_plci[ncci] = 0;
975         a->ncci_state[ncci] = IDLE;
976         i = plci->ncci_ring_list;
977         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
978           i = a->ncci_next[i];
979         if ((i != 0) && (a->ncci_next[i] == ncci))
980         {
981           if (i == ncci)
982             plci->ncci_ring_list = 0;
983           else if (plci->ncci_ring_list == ncci)
984             plci->ncci_ring_list = i;
985           a->ncci_next[i] = a->ncci_next[ncci];
986         }
987         a->ncci_next[ncci] = 0;
988       }
989     }
990   }
991   else
992   {
993     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
994     {
995       if (a->ncci_plci[ncci] == plci->Id)
996       {
997         cleanup_ncci_data (plci, ncci);
998         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
999           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
1000         a->ch_ncci[a->ncci_ch[ncci]] = 0;
1001         if (!preserve_ncci)
1002         {
1003           a->ncci_ch[ncci] = 0;
1004           a->ncci_plci[ncci] = 0;
1005           a->ncci_state[ncci] = IDLE;
1006           a->ncci_next[ncci] = 0;
1007         }
1008       }
1009     }
1010     if (!preserve_ncci)
1011       plci->ncci_ring_list = 0;
1012   }
1013 }
1014
1015
1016 /*------------------------------------------------------------------*/
1017 /* PLCI remove function                                             */
1018 /*------------------------------------------------------------------*/
1019
1020 static void plci_free_msg_in_queue (PLCI   *plci)
1021 {
1022   word i;
1023
1024   if (plci->appl)
1025   {
1026     i = plci->msg_in_read_pos;
1027     while (i != plci->msg_in_write_pos)
1028     {
1029       if (i == plci->msg_in_wrap_pos)
1030         i = 0;
1031       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1032       {
1033
1034         TransmitBufferFree (plci->appl,
1035           (byte   *)(((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1036
1037       }
1038
1039       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1040         MSG_IN_OVERHEAD + 3) & 0xfffc;
1041
1042     }
1043   }
1044   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1045   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1046   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1047 }
1048
1049
1050 static void plci_remove(PLCI   * plci)
1051 {
1052
1053   if(!plci) {
1054     dbug(1,dprintf("plci_remove(no plci)"));
1055     return;
1056   }
1057   init_internal_command_queue (plci);
1058   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1059   if(plci_remove_check(plci))
1060   {
1061     return;
1062   }
1063   if (plci->Sig.Id == 0xff)
1064   {
1065     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1066     if (plci->NL.Id && !plci->nl_remove_id)
1067     {
1068       nl_req_ncci(plci,REMOVE,0);
1069       send_req(plci);
1070     }
1071   }
1072   else
1073   {
1074     if (!plci->sig_remove_id
1075      && (plci->Sig.Id
1076       || (plci->req_in!=plci->req_out)
1077       || (plci->nl_req || plci->sig_req)))
1078     {
1079       sig_req(plci,HANGUP,0);
1080       send_req(plci);
1081     }
1082   }
1083   ncci_remove (plci, 0, FALSE);
1084   plci_free_msg_in_queue (plci);
1085
1086   plci->channels = 0;
1087   plci->appl = NULL;
1088   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1089     plci->State = OUTG_DIS_PENDING;
1090 }
1091
1092 /*------------------------------------------------------------------*/
1093 /* Application Group function helpers                               */
1094 /*------------------------------------------------------------------*/
1095
1096 static void set_group_ind_mask (PLCI   *plci)
1097 {
1098   word i;
1099
1100   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1101     plci->group_optimization_mask_table[i] = 0xffffffffL;
1102 }
1103
1104 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1105 {
1106   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1107 }
1108
1109 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1110 {
1111   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1112 }
1113
1114 /*------------------------------------------------------------------*/
1115 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1116 /*------------------------------------------------------------------*/
1117
1118 static void clear_c_ind_mask (PLCI   *plci)
1119 {
1120   word i;
1121
1122   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1123     plci->c_ind_mask_table[i] = 0;
1124 }
1125
1126 static byte c_ind_mask_empty (PLCI   *plci)
1127 {
1128   word i;
1129
1130   i = 0;
1131   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1132     i++;
1133   return (i == C_IND_MASK_DWORDS);
1134 }
1135
1136 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1137 {
1138   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1139 }
1140
1141 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1142 {
1143   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1144 }
1145
1146 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1147 {
1148   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1149 }
1150
1151 static void dump_c_ind_mask (PLCI   *plci)
1152 {
1153 static char hex_digit_table[0x10] =
1154   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1155   word i, j, k;
1156   dword d;
1157     char *p;
1158     char buf[40];
1159
1160   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1161   {
1162     p = buf + 36;
1163     *p = '\0';
1164     for (j = 0; j < 4; j++)
1165     {
1166       if (i+j < C_IND_MASK_DWORDS)
1167       {
1168         d = plci->c_ind_mask_table[i+j];
1169         for (k = 0; k < 8; k++)
1170         {
1171           *(--p) = hex_digit_table[d & 0xf];
1172           d >>= 4;
1173         }
1174       }
1175       else if (i != 0)
1176       {
1177         for (k = 0; k < 8; k++)
1178           *(--p) = ' ';
1179       }
1180       *(--p) = ' ';
1181     }
1182     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1183   }
1184 }
1185
1186
1187
1188
1189
1190 #define dump_plcis(a)
1191
1192
1193
1194 /*------------------------------------------------------------------*/
1195 /* translation function for each message                            */
1196 /*------------------------------------------------------------------*/
1197
1198 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1199 {
1200   word ch;
1201   word i;
1202   word Info;
1203   word CIP;
1204   byte LinkLayer;
1205   API_PARSE * ai;
1206   API_PARSE * bp;
1207     API_PARSE ai_parms[5];
1208   word channel = 0;
1209   dword ch_mask;
1210   byte m;
1211   static byte esc_chi[35] = {0x02,0x18,0x01};
1212   static byte lli[2] = {0x01,0x00};
1213   byte noCh = 0;
1214   word dir = 0;
1215   byte   *p_chi = "";
1216
1217   for(i=0;i<5;i++) ai_parms[i].length = 0;
1218
1219   dbug(1,dprintf("connect_req(%d)",parms->length));
1220   Info = _WRONG_IDENTIFIER;
1221   if(a)
1222   {
1223     if(a->adapter_disabled)
1224     {
1225       dbug(1,dprintf("adapter disabled"));
1226       Id = ((word)1<<8)|a->Id;
1227       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1228       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1229       return FALSE;
1230     }
1231     Info = _OUT_OF_PLCI;
1232     if((i=get_plci(a)))
1233     {
1234       Info = 0;
1235       plci = &a->plci[i-1];
1236       plci->appl = appl;
1237       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1238       /* check 'external controller' bit for codec support */
1239       if(Id & EXT_CONTROLLER)
1240       {
1241         if(AdvCodecSupport(a, plci, appl, 0) )
1242         {
1243           plci->Id = 0;
1244           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1245           return 2;
1246         }
1247       }
1248       ai = &parms[9];
1249       bp = &parms[5];
1250       ch = 0;
1251       if(bp->length)LinkLayer = bp->info[3];
1252       else LinkLayer = 0;
1253       if(ai->length)
1254       {
1255         ch=0xffff;
1256         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1257         {
1258           ch = 0;
1259           if(ai_parms[0].length)
1260           {
1261             ch = GET_WORD(ai_parms[0].info+1);
1262             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1263             if(ch==4) /* explizit CHI in message */
1264             {
1265               /* check length of B-CH struct */
1266               if((ai_parms[0].info)[3]>=1)
1267               {
1268                 if((ai_parms[0].info)[4]==CHI)
1269                 {
1270                   p_chi = &((ai_parms[0].info)[5]);
1271                 }
1272                 else
1273                 {
1274                   p_chi = &((ai_parms[0].info)[3]);
1275                 }
1276                 if(p_chi[0]>35) /* check length of channel ID */
1277                 {
1278                   Info = _WRONG_MESSAGE_FORMAT;    
1279                 }
1280               }
1281               else Info = _WRONG_MESSAGE_FORMAT;    
1282             }
1283
1284             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1285             {
1286               dir = GET_WORD(ai_parms[0].info+3);
1287               ch_mask = 0;
1288               m = 0x3f;
1289               for(i=0; i+5<=ai_parms[0].length; i++)
1290               {
1291                 if(ai_parms[0].info[i+5]!=0)
1292                 {
1293                   if((ai_parms[0].info[i+5] | m) != 0xff)
1294                     Info = _WRONG_MESSAGE_FORMAT;
1295                   else
1296                   {
1297                     if (ch_mask == 0)
1298                       channel = i;
1299                     ch_mask |= 1L << i;
1300                   }
1301                 }
1302                 m = 0;
1303               }
1304               if (ch_mask == 0)
1305                 Info = _WRONG_MESSAGE_FORMAT;
1306               if (!Info)
1307               {
1308                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1309                 {
1310                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1311                   for(i=0; i+5<=ai_parms[0].length; i++)
1312                     esc_chi[i+3] = ai_parms[0].info[i+5];
1313                 }
1314                 else
1315                   esc_chi[0] = 2;
1316                 esc_chi[2] = (byte)channel;
1317                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1318                 add_p(plci,LLI,lli);
1319                 add_p(plci,ESC,esc_chi);
1320                 plci->State = LOCAL_CONNECT;
1321                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1322               }
1323             }
1324           }
1325         }
1326         else  Info = _WRONG_MESSAGE_FORMAT;
1327       }
1328
1329       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1330       plci->command = _CONNECT_R;
1331       plci->number = Number;
1332       /* x.31 or D-ch free SAPI in LinkLayer? */
1333       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = TRUE;
1334       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1335       {
1336         /* B-channel used for B3 connections (ch==0), or no B channel    */
1337         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1338         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1339         else     Info = add_b1(plci,&parms[5],ch,0); 
1340         add_s(plci,OAD,&parms[2]);
1341         add_s(plci,OSA,&parms[4]);
1342         add_s(plci,BC,&parms[6]);
1343         add_s(plci,LLC,&parms[7]);
1344         add_s(plci,HLC,&parms[8]);
1345         CIP = GET_WORD(parms[0].info);
1346         if (a->Info_Mask[appl->Id-1] & 0x200)
1347         {
1348           /* early B3 connect (CIP mask bit 9) no release after a disc */
1349           add_p(plci,LLI,"\x01\x01");
1350         }
1351         if(GET_WORD(parms[0].info)<29) {
1352           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1353           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1354         }
1355         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1356         sig_req(plci,ASSIGN,DSIG_ID);
1357       }
1358       else if(ch==1) {
1359
1360         /* D-Channel used for B3 connections */
1361         plci->Sig.Id = 0xff;
1362         Info = 0;
1363       }
1364
1365       if(!Info && ch!=2 && !noCh ) {
1366         Info = add_b23(plci,&parms[5]);
1367         if(!Info) {
1368           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1369         }
1370       }
1371
1372       if(!Info)
1373       {
1374         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1375         {
1376           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1377           {
1378             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1379             plci->spoofed_msg = CALL_REQ;
1380             plci->internal_command = BLOCK_PLCI;
1381             plci->command = 0;
1382             dbug(1,dprintf("Spoof"));
1383             send_req(plci);
1384             return FALSE;
1385           }
1386           if(ch==4)add_p(plci,CHI,p_chi);
1387           add_s(plci,CPN,&parms[1]);
1388           add_s(plci,DSA,&parms[3]);
1389           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1390           add_ai(plci,&parms[9]);
1391           if(!dir)sig_req(plci,CALL_REQ,0);
1392           else
1393           {
1394             plci->command = PERM_LIST_REQ;
1395             plci->appl = appl;
1396             sig_req(plci,LISTEN_REQ,0);
1397             send_req(plci);
1398             return FALSE;
1399           }
1400         }
1401         send_req(plci);
1402         return FALSE;
1403       }
1404       plci->Id = 0;
1405     }
1406   }
1407   sendf(appl,
1408         _CONNECT_R|CONFIRM,
1409         Id,
1410         Number,
1411         "w",Info);
1412   return 2;
1413 }
1414
1415 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1416 {
1417   word i, Info;
1418   word Reject;
1419   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1420   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1421   API_PARSE * ai;
1422     API_PARSE ai_parms[5];
1423   word ch=0;
1424
1425   if(!plci) {
1426     dbug(1,dprintf("connect_res(no plci)"));
1427     return 0;  /* no plci, no send */
1428   }
1429
1430   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1431   for(i=0;i<5;i++) ai_parms[i].length = 0;
1432   ai = &parms[5];
1433   dbug(1,dprintf("ai->length=%d",ai->length));
1434
1435   if(ai->length)
1436   {
1437     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1438     {
1439       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1440       ch = 0;
1441       if(ai_parms[0].length)
1442       {
1443         ch = GET_WORD(ai_parms[0].info+1);
1444         dbug(1,dprintf("BCH-I=0x%x",ch));
1445       }
1446     }
1447   }
1448
1449   if(plci->State==INC_CON_CONNECTED_ALERT)
1450   {
1451     dbug(1,dprintf("Connected Alert Call_Res"));
1452     if (a->Info_Mask[appl->Id-1] & 0x200)
1453     {
1454     /* early B3 connect (CIP mask bit 9) no release after a disc */
1455       add_p(plci,LLI,"\x01\x01");
1456     }
1457     add_s(plci, CONN_NR, &parms[2]);
1458     add_s(plci, LLC, &parms[4]);
1459     add_ai(plci, &parms[5]);
1460     plci->State = INC_CON_ACCEPT;
1461     sig_req(plci, CALL_RES,0);
1462     return 1;
1463   }
1464   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1465     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1466     dump_c_ind_mask (plci);
1467     Reject = GET_WORD(parms[0].info);
1468     dbug(1,dprintf("Reject=0x%x",Reject));
1469     if(Reject) 
1470     {
1471       if(c_ind_mask_empty (plci)) 
1472       {
1473         if((Reject&0xff00)==0x3400) 
1474         {
1475           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1476           add_p(plci,ESC,esc_t);
1477           add_ai(plci, &parms[5]);
1478           sig_req(plci,REJECT,0);
1479         }      
1480         else if(Reject==1 || Reject>9) 
1481         {
1482           add_ai(plci, &parms[5]);
1483           sig_req(plci,HANGUP,0);
1484         }
1485         else 
1486         {
1487           esc_t[2] = cau_t[(Reject&0x000f)];
1488           add_p(plci,ESC,esc_t);
1489           add_ai(plci, &parms[5]);
1490           sig_req(plci,REJECT,0);
1491         }
1492         plci->appl = appl;
1493       }
1494       else 
1495       {
1496         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1497       }
1498     }
1499     else {
1500       plci->appl = appl;
1501       if(Id & EXT_CONTROLLER){
1502         if(AdvCodecSupport(a, plci, appl, 0)){
1503           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1504           sig_req(plci,HANGUP,0);
1505           return 1;
1506         }
1507         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1508         {
1509           Info = add_b23(plci, &parms[1]);
1510           if (Info)
1511           {
1512             dbug(1,dprintf("connect_res(error from add_b23)"));
1513             sig_req(plci,HANGUP,0);
1514             return 1;
1515           }
1516           if(plci->adv_nl)
1517           {
1518             nl_req_ncci(plci, ASSIGN, 0);
1519           }
1520         }
1521       }
1522       else
1523       {
1524         plci->tel = 0;
1525         if(ch!=2)
1526         {
1527           Info = add_b23(plci, &parms[1]);
1528           if (Info)
1529           {
1530             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1531             sig_req(plci,HANGUP,0);
1532             return 1;
1533           }
1534         }
1535         nl_req_ncci(plci, ASSIGN, 0);
1536       }
1537
1538       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1539       {
1540         api_save_msg(parms, "wsssss", &plci->saved_msg);
1541         plci->spoofed_msg = CALL_RES;
1542         plci->internal_command = BLOCK_PLCI;
1543         plci->command = 0;
1544         dbug(1,dprintf("Spoof"));
1545       }
1546       else
1547       {
1548         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1549         if (a->Info_Mask[appl->Id-1] & 0x200)
1550         {
1551           /* early B3 connect (CIP mask bit 9) no release after a disc */
1552           add_p(plci,LLI,"\x01\x01");
1553         }
1554         add_s(plci, CONN_NR, &parms[2]);
1555         add_s(plci, LLC, &parms[4]);
1556         add_ai(plci, &parms[5]);
1557         plci->State = INC_CON_ACCEPT;
1558         sig_req(plci, CALL_RES,0);
1559       }
1560
1561       for(i=0; i<max_appl; i++) {
1562         if(test_c_ind_mask_bit (plci, i)) {
1563           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1564         }
1565       }
1566     }
1567   }
1568   return 1;
1569 }
1570
1571 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1572 {
1573   dbug(1,dprintf("connect_a_res"));
1574   return FALSE;
1575 }
1576
1577 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1578 {
1579   word Info;
1580   word i;
1581
1582   dbug(1,dprintf("disconnect_req"));
1583
1584   Info = _WRONG_IDENTIFIER;
1585
1586   if(plci)
1587   {
1588     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1589     {
1590       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1591       plci->appl = appl;
1592       for(i=0; i<max_appl; i++)
1593       {
1594         if(test_c_ind_mask_bit (plci, i))
1595           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1596       }
1597       plci->State = OUTG_DIS_PENDING;
1598     }
1599     if(plci->Sig.Id && plci->appl)
1600     {
1601       Info = 0;
1602         if(plci->Sig.Id!=0xff)
1603         {
1604           if(plci->State!=INC_DIS_PENDING)
1605           {
1606             add_ai(plci, &msg[0]);
1607             sig_req(plci,HANGUP,0);
1608             plci->State = OUTG_DIS_PENDING;
1609             return 1;
1610           }
1611         }
1612         else
1613         {
1614           if (plci->NL.Id && !plci->nl_remove_id)
1615           {
1616             mixer_remove (plci);
1617             nl_req_ncci(plci,REMOVE,0);
1618           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1619           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1620           plci->State = INC_DIS_PENDING;
1621           }
1622           return 1;
1623         }
1624       }
1625     }
1626
1627   if(!appl)  return FALSE;
1628   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1629   return FALSE;
1630 }
1631
1632 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1633 {
1634   dbug(1,dprintf("disconnect_res"));
1635   if(plci)
1636   {
1637         /* clear ind mask bit, just in case of collsion of          */
1638         /* DISCONNECT_IND and CONNECT_RES                           */
1639     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1640     ncci_free_receive_buffers (plci, 0);
1641     if(plci_remove_check(plci))
1642     {
1643       return 0;
1644     }
1645     if(plci->State==INC_DIS_PENDING
1646     || plci->State==SUSPENDING) {
1647       if(c_ind_mask_empty (plci)) {
1648         if(plci->State!=SUSPENDING)plci->State = IDLE;
1649         dbug(1,dprintf("chs=%d",plci->channels));
1650         if(!plci->channels) {
1651           plci_remove(plci);
1652         }
1653       }
1654     }
1655   }
1656   return 0;
1657 }
1658
1659 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1660 {
1661   word Info;
1662   byte i;
1663
1664   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1665
1666   Info = _WRONG_IDENTIFIER;
1667   if(a) {
1668     Info = 0;
1669     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1670     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1671     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1672     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1673       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1674     }
1675
1676     /* check if external controller listen and switch listen on or off*/
1677     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1678       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1679         dummy_plci.State = IDLE;
1680         a->codec_listen[appl->Id-1] = &dummy_plci;
1681         a->TelOAD[0] = (byte)(parms[3].length);
1682         for(i=1;parms[3].length>=i && i<22;i++) {
1683           a->TelOAD[i] = parms[3].info[i];
1684         }
1685         a->TelOAD[i] = 0;
1686         a->TelOSA[0] = (byte)(parms[4].length);
1687         for(i=1;parms[4].length>=i && i<22;i++) {
1688           a->TelOSA[i] = parms[4].info[i];
1689         }
1690         a->TelOSA[i] = 0;
1691       }
1692       else Info = 0x2002; /* wrong controller, codec not supported */
1693     }
1694     else{               /* clear listen */
1695       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1696     }
1697   }
1698   sendf(appl,
1699         _LISTEN_R|CONFIRM,
1700         Id,
1701         Number,
1702         "w",Info);
1703
1704   if (a) listen_check(a);
1705   return FALSE;
1706 }
1707
1708 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1709 {
1710   word i;
1711   API_PARSE * ai;
1712   PLCI   * rc_plci = NULL;
1713     API_PARSE ai_parms[5];
1714   word Info = 0;
1715
1716   dbug(1,dprintf("info_req"));
1717   for(i=0;i<5;i++) ai_parms[i].length = 0;
1718
1719   ai = &msg[1];
1720
1721   if(ai->length)
1722   {
1723     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1724     {
1725       dbug(1,dprintf("AddInfo wrong"));
1726       Info = _WRONG_MESSAGE_FORMAT;
1727     }
1728   }
1729   if(!a) Info = _WRONG_STATE;
1730
1731   if(!Info && plci)
1732   {                /* no fac, with CPN, or KEY */
1733     rc_plci = plci;
1734     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1735     {
1736       /* overlap sending option */
1737       dbug(1,dprintf("OvlSnd"));
1738       add_s(plci,CPN,&msg[0]);
1739       add_s(plci,KEY,&ai_parms[1]);
1740       sig_req(plci,INFO_REQ,0);
1741       send_req(plci);
1742       return FALSE;
1743     }
1744
1745     if(plci->State && ai_parms[2].length)
1746     {
1747       /* User_Info option */
1748       dbug(1,dprintf("UUI"));
1749       add_s(plci,UUI,&ai_parms[2]);
1750       sig_req(plci,USER_DATA,0);
1751     }
1752     else if(plci->State && ai_parms[3].length)
1753     {
1754       /* Facility option */
1755       dbug(1,dprintf("FAC"));
1756       add_s(plci,CPN,&msg[0]);
1757       add_ai(plci, &msg[1]);
1758       sig_req(plci,FACILITY_REQ,0);
1759     }
1760     else
1761     {
1762       Info = _WRONG_STATE;
1763     }
1764   }
1765   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766   {
1767     /* NCR_Facility option -> send UUI and Keypad too */
1768     dbug(1,dprintf("NCR_FAC"));
1769     if((i=get_plci(a)))
1770     {
1771       rc_plci = &a->plci[i-1];
1772       appl->NullCREnable  = TRUE;
1773       rc_plci->internal_command = C_NCR_FAC_REQ;
1774       rc_plci->appl = appl;
1775       add_p(rc_plci,CAI,"\x01\x80");
1776       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1777       sig_req(rc_plci,ASSIGN,DSIG_ID);
1778       send_req(rc_plci);
1779     }
1780     else
1781     {
1782       Info = _OUT_OF_PLCI;
1783     }
1784
1785     if(!Info)
1786     {
1787       add_s(rc_plci,CPN,&msg[0]);
1788       add_ai(rc_plci, &msg[1]);
1789       sig_req(rc_plci,NCR_FACILITY,0);
1790       send_req(rc_plci);
1791       return FALSE;
1792      /* for application controlled supplementary services    */
1793     }
1794   }
1795
1796   if (!rc_plci)
1797   {
1798     Info = _WRONG_MESSAGE_FORMAT;
1799   }
1800
1801   if(!Info)
1802   {
1803     send_req(rc_plci);
1804   }
1805   else
1806   {  /* appl is not assigned to a PLCI or error condition */
1807     dbug(1,dprintf("localInfoCon"));
1808     sendf(appl,
1809           _INFO_R|CONFIRM,
1810           Id,
1811           Number,
1812           "w",Info);
1813   }
1814   return FALSE;
1815 }
1816
1817 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1818 {
1819   dbug(1,dprintf("info_res"));
1820   return FALSE;
1821 }
1822
1823 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1824 {
1825   word Info;
1826   byte ret;
1827
1828   dbug(1,dprintf("alert_req"));
1829
1830   Info = _WRONG_IDENTIFIER;
1831   ret = FALSE;
1832   if(plci) {
1833     Info = _ALERT_IGNORED;
1834     if(plci->State!=INC_CON_ALERT) {
1835       Info = _WRONG_STATE;
1836       if(plci->State==INC_CON_PENDING) {
1837         Info = 0;
1838         plci->State=INC_CON_ALERT;
1839         add_ai(plci, &msg[0]);
1840         sig_req(plci,CALL_ALERT,0);
1841         ret = 1;
1842       }
1843     }
1844   }
1845   sendf(appl,
1846         _ALERT_R|CONFIRM,
1847         Id,
1848         Number,
1849         "w",Info);
1850   return ret;
1851 }
1852
1853 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1854 {
1855   word Info = 0;
1856   word i    = 0;
1857
1858   word selector;
1859   word SSreq;
1860   long relatedPLCIvalue;
1861   DIVA_CAPI_ADAPTER   * relatedadapter;
1862   byte * SSparms  = "";
1863     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1864     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1865   API_PARSE * parms;
1866     API_PARSE ss_parms[11];
1867   PLCI   *rplci;
1868     byte cai[15];
1869   dword d;
1870     API_PARSE dummy;
1871
1872   dbug(1,dprintf("facility_req"));
1873   for(i=0;i<9;i++) ss_parms[i].length = 0;
1874
1875   parms = &msg[1];
1876
1877   if(!a)
1878   {
1879     dbug(1,dprintf("wrong Ctrl"));
1880     Info = _WRONG_IDENTIFIER;
1881   }
1882
1883   selector = GET_WORD(msg[0].info);
1884
1885   if(!Info)
1886   {
1887     switch(selector)
1888     {
1889       case SELECTOR_HANDSET:
1890         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1891         break;
1892
1893       case SELECTOR_SU_SERV:
1894         if(!msg[1].length)
1895         {
1896           Info = _WRONG_MESSAGE_FORMAT;
1897           break;
1898         }
1899         SSreq = GET_WORD(&(msg[1].info[1]));
1900         PUT_WORD(&RCparms[1],SSreq);
1901         SSparms = RCparms;
1902         switch(SSreq)
1903         {
1904           case S_GET_SUPPORTED_SERVICES:
1905             if((i=get_plci(a)))
1906             {
1907               rplci = &a->plci[i-1];
1908               rplci->appl = appl;
1909               add_p(rplci,CAI,"\x01\x80");
1910               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1911               sig_req(rplci,ASSIGN,DSIG_ID);
1912               send_req(rplci);
1913             }
1914             else
1915             {
1916               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1917               SSparms = (byte *)SSstruct;
1918               break;
1919             }
1920             rplci->internal_command = GETSERV_REQ_PEND;
1921             rplci->number = Number;
1922             rplci->appl = appl;
1923             sig_req(rplci,S_SUPPORTED,0);
1924             send_req(rplci);
1925             return FALSE;
1926             break;
1927
1928           case S_LISTEN:
1929             if(parms->length==7)
1930             {
1931               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1932               {
1933                 dbug(1,dprintf("format wrong"));
1934                 Info = _WRONG_MESSAGE_FORMAT;
1935                 break;
1936               }
1937             }
1938             else
1939             {
1940               Info = _WRONG_MESSAGE_FORMAT;
1941               break;
1942             }
1943             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1944             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1945             {
1946               if((i=get_plci(a)))
1947               {
1948                 rplci = &a->plci[i-1];
1949                 rplci->appl = appl;
1950                 add_p(rplci,CAI,"\x01\x80");
1951                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1952                 sig_req(rplci,ASSIGN,DSIG_ID);
1953                 send_req(rplci);
1954               }
1955               else
1956               {
1957                 break;
1958               }
1959               rplci->internal_command = GET_MWI_STATE;
1960               rplci->number = Number;
1961               sig_req(rplci,MWI_POLL,0);
1962               send_req(rplci);
1963             }
1964             break;
1965
1966           case S_HOLD:
1967             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1968             if(plci && plci->State && plci->SuppState==IDLE)
1969             {
1970               plci->SuppState = HOLD_REQUEST;
1971               plci->command = C_HOLD_REQ;
1972               add_s(plci,CAI,&ss_parms[1]);
1973               sig_req(plci,CALL_HOLD,0);
1974               send_req(plci);
1975               return FALSE;
1976             }
1977             else Info = 0x3010;                    /* wrong state           */
1978             break;
1979           case S_RETRIEVE:
1980             if(plci && plci->State && plci->SuppState==CALL_HELD)
1981             {
1982               if(Id & EXT_CONTROLLER)
1983               {
1984                 if(AdvCodecSupport(a, plci, appl, 0))
1985                 {
1986                   Info = 0x3010;                    /* wrong state           */
1987                   break;
1988                 }
1989               }
1990               else plci->tel = 0;
1991
1992               plci->SuppState = RETRIEVE_REQUEST;
1993               plci->command = C_RETRIEVE_REQ;
1994               if(plci->spoofed_msg==SPOOFING_REQUIRED)
1995               {
1996                 plci->spoofed_msg = CALL_RETRIEVE;
1997                 plci->internal_command = BLOCK_PLCI;
1998                 plci->command = 0;
1999                 dbug(1,dprintf("Spoof"));
2000                 return FALSE;
2001               }
2002               else
2003               {
2004                 sig_req(plci,CALL_RETRIEVE,0);
2005                 send_req(plci);
2006                 return FALSE;
2007               }
2008             }
2009             else Info = 0x3010;                    /* wrong state           */
2010             break;
2011           case S_SUSPEND:
2012             if(parms->length)
2013             {
2014               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2015               {
2016                 dbug(1,dprintf("format wrong"));
2017                 Info = _WRONG_MESSAGE_FORMAT;
2018                 break;
2019               }
2020             }
2021             if(plci && plci->State)
2022             {
2023               add_s(plci,CAI,&ss_parms[2]);
2024               plci->command = SUSPEND_REQ;
2025               sig_req(plci,SUSPEND,0);
2026               plci->State = SUSPENDING;
2027               send_req(plci);
2028             }
2029             else Info = 0x3010;                    /* wrong state           */
2030             break;
2031
2032           case S_RESUME:
2033             if(!(i=get_plci(a)) )
2034             {
2035               Info = _OUT_OF_PLCI;
2036               break;
2037             }
2038             rplci = &a->plci[i-1];
2039             rplci->appl = appl;
2040             rplci->number = Number;
2041             rplci->tel = 0;
2042             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2043             /* check 'external controller' bit for codec support */
2044             if(Id & EXT_CONTROLLER)
2045             {
2046               if(AdvCodecSupport(a, rplci, appl, 0) )
2047               {
2048                 rplci->Id = 0;
2049                 Info = 0x300A;
2050                 break;
2051               }
2052             }
2053             if(parms->length)
2054             {
2055               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2056               {
2057                 dbug(1,dprintf("format wrong"));
2058                 rplci->Id = 0;
2059                 Info = _WRONG_MESSAGE_FORMAT;
2060                 break;
2061               }
2062             }
2063             dummy.length = 0;
2064             dummy.info = "\x00";
2065             add_b1(rplci, &dummy, 0, 0);
2066             if (a->Info_Mask[appl->Id-1] & 0x200)
2067             {
2068               /* early B3 connect (CIP mask bit 9) no release after a disc */
2069               add_p(rplci,LLI,"\x01\x01");
2070             }
2071             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2072             sig_req(rplci,ASSIGN,DSIG_ID);
2073             send_req(rplci);
2074             add_s(rplci,CAI,&ss_parms[2]);
2075             rplci->command = RESUME_REQ;
2076             sig_req(rplci,RESUME,0);
2077             rplci->State = RESUMING;
2078             send_req(rplci);
2079             break;
2080
2081           case S_CONF_BEGIN: /* Request */
2082           case S_CONF_DROP:
2083           case S_CONF_ISOLATE:
2084           case S_CONF_REATTACH:
2085             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2086             {
2087               dbug(1,dprintf("format wrong"));
2088               Info = _WRONG_MESSAGE_FORMAT;
2089               break;
2090             }
2091             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2092             {
2093               d = GET_DWORD(ss_parms[2].info);     
2094               if(d>=0x80)
2095               {
2096                 dbug(1,dprintf("format wrong"));
2097                 Info = _WRONG_MESSAGE_FORMAT;
2098                 break;
2099               }
2100               plci->ptyState = (byte)SSreq;
2101               plci->command = 0;
2102               cai[0] = 2;
2103               switch(SSreq)
2104               {
2105               case S_CONF_BEGIN:
2106                   cai[1] = CONF_BEGIN;
2107                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2108                   break;
2109               case S_CONF_DROP:
2110                   cai[1] = CONF_DROP;
2111                   plci->internal_command = CONF_DROP_REQ_PEND;
2112                   break;
2113               case S_CONF_ISOLATE:
2114                   cai[1] = CONF_ISOLATE;
2115                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2116                   break;
2117               case S_CONF_REATTACH:
2118                   cai[1] = CONF_REATTACH;
2119                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2120                   break;
2121               }
2122               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2123               add_p(plci,CAI,cai);
2124               sig_req(plci,S_SERVICE,0);
2125               send_req(plci);
2126               return FALSE;
2127             }
2128             else Info = 0x3010;                    /* wrong state           */
2129             break;
2130
2131           case S_ECT:
2132           case S_3PTY_BEGIN:
2133           case S_3PTY_END:
2134           case S_CONF_ADD:
2135             if(parms->length==7)
2136             {
2137               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2138               {
2139                 dbug(1,dprintf("format wrong"));
2140                 Info = _WRONG_MESSAGE_FORMAT;
2141                 break;
2142               }
2143             }
2144             else if(parms->length==8) /* workaround for the T-View-S */
2145             {
2146               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2147               {
2148                 dbug(1,dprintf("format wrong"));
2149                 Info = _WRONG_MESSAGE_FORMAT;
2150                 break;
2151               }
2152             }
2153             else
2154             {
2155               Info = _WRONG_MESSAGE_FORMAT;
2156               break;
2157             }
2158             if(!msg[1].length)
2159             {
2160               Info = _WRONG_MESSAGE_FORMAT;
2161               break;
2162             }
2163             if (!plci)
2164             {
2165               Info = _WRONG_IDENTIFIER;
2166               break;
2167             }
2168             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2169             relatedPLCIvalue &= 0x0000FFFF;
2170             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2171             /* controller starts with 0 up to (max_adapter - 1) */
2172             if (((relatedPLCIvalue & 0x7f) == 0)
2173              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2174              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2175             {
2176               if(SSreq==S_3PTY_END)
2177               {
2178                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2179                 rplci = plci;
2180               }
2181               else
2182               {
2183                 Info = 0x3010;                    /* wrong state           */
2184                 break;
2185               }
2186             }
2187             else
2188             {  
2189               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2190               relatedPLCIvalue >>=8;
2191               /* find PLCI PTR*/
2192               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2193               {
2194                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2195                 {
2196                   rplci = &relatedadapter->plci[i];
2197                 }
2198               }
2199               if(!rplci || !relatedPLCIvalue)
2200               {
2201                 if(SSreq==S_3PTY_END)
2202                 {
2203                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2204                   rplci = plci;
2205                 }
2206                 else
2207                 {
2208                   Info = 0x3010;                    /* wrong state           */
2209                   break;
2210                 }
2211               }
2212             }
2213 /*
2214             dbug(1,dprintf("rplci:%x",rplci));
2215             dbug(1,dprintf("plci:%x",plci));
2216             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2217             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2218             dbug(1,dprintf("SSreq:%x",SSreq));
2219             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2220             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2221             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2222 */
2223             /* send PTY/ECT req, cannot check all states because of US stuff */
2224             if( !rplci->internal_command && rplci->appl )
2225             {
2226               plci->command = 0;
2227               rplci->relatedPTYPLCI = plci;
2228               plci->relatedPTYPLCI = rplci;
2229               rplci->ptyState = (byte)SSreq;
2230               if(SSreq==S_ECT)
2231               {
2232                 rplci->internal_command = ECT_REQ_PEND;
2233                 cai[1] = ECT_EXECUTE;
2234
2235                 rplci->vswitchstate=0;
2236                 rplci->vsprot=0;
2237                 rplci->vsprotdialect=0;
2238                 plci->vswitchstate=0;
2239                 plci->vsprot=0;
2240                 plci->vsprotdialect=0;
2241
2242               }
2243               else if(SSreq==S_CONF_ADD)
2244               {
2245                 rplci->internal_command = CONF_ADD_REQ_PEND;
2246                 cai[1] = CONF_ADD;
2247               }
2248               else
2249               {
2250                 rplci->internal_command = PTY_REQ_PEND;
2251                 cai[1] = (byte)(SSreq-3);
2252               }
2253               rplci->number = Number;
2254               if(plci!=rplci) /* explicit invocation */
2255               {
2256                 cai[0] = 2;
2257                 cai[2] = plci->Sig.Id;
2258                 dbug(1,dprintf("explicit invocation"));
2259               }
2260               else
2261               {
2262                 dbug(1,dprintf("implicit invocation"));
2263                 cai[0] = 1;
2264               }
2265               add_p(rplci,CAI,cai);
2266               sig_req(rplci,S_SERVICE,0);
2267               send_req(rplci);
2268               return FALSE;
2269             }
2270             else
2271             {
2272               dbug(0,dprintf("Wrong line"));
2273               Info = 0x3010;                    /* wrong state           */
2274               break;
2275             }
2276             break;
2277
2278           case S_CALL_DEFLECTION:
2279             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2280             {
2281               dbug(1,dprintf("format wrong"));
2282               Info = _WRONG_MESSAGE_FORMAT;
2283               break;
2284             }
2285             if (!plci)
2286             {
2287               Info = _WRONG_IDENTIFIER;
2288               break;
2289             }
2290             /* reuse unused screening indicator */
2291             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2292             plci->command = 0;
2293             plci->internal_command = CD_REQ_PEND;
2294             appl->CDEnable = TRUE;
2295             cai[0] = 1;
2296             cai[1] = CALL_DEFLECTION;
2297             add_p(plci,CAI,cai);
2298             add_p(plci,CPN,ss_parms[3].info);
2299             sig_req(plci,S_SERVICE,0);
2300             send_req(plci);
2301             return FALSE;
2302             break;
2303
2304           case S_CALL_FORWARDING_START:
2305             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2306             {
2307               dbug(1,dprintf("format wrong"));
2308               Info = _WRONG_MESSAGE_FORMAT;
2309               break;
2310             }
2311
2312             if((i=get_plci(a)))
2313             {
2314               rplci = &a->plci[i-1];
2315               rplci->appl = appl;
2316               add_p(rplci,CAI,"\x01\x80");
2317               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2318               sig_req(rplci,ASSIGN,DSIG_ID);
2319               send_req(rplci);
2320             }
2321             else
2322             {
2323               Info = _OUT_OF_PLCI;
2324               break;
2325             }
2326
2327             /* reuse unused screening indicator */
2328             rplci->internal_command = CF_START_PEND;
2329             rplci->appl = appl;
2330             rplci->number = Number;
2331             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2332             cai[0] = 2;
2333             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2334             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2335             add_p(rplci,CAI,cai);
2336             add_p(rplci,OAD,ss_parms[5].info);
2337             add_p(rplci,CPN,ss_parms[6].info);
2338             sig_req(rplci,S_SERVICE,0);
2339             send_req(rplci);
2340             return FALSE;
2341             break;
2342
2343           case S_INTERROGATE_DIVERSION:
2344           case S_INTERROGATE_NUMBERS:
2345           case S_CALL_FORWARDING_STOP:
2346           case S_CCBS_REQUEST:
2347           case S_CCBS_DEACTIVATE:
2348           case S_CCBS_INTERROGATE:
2349             switch(SSreq)
2350             {
2351             case S_INTERROGATE_NUMBERS:
2352                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2353                 {
2354                   dbug(0,dprintf("format wrong"));
2355                   Info = _WRONG_MESSAGE_FORMAT;
2356                 }
2357                 break;
2358             case S_CCBS_REQUEST:
2359             case S_CCBS_DEACTIVATE:
2360                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2361                 {
2362                   dbug(0,dprintf("format wrong"));
2363                   Info = _WRONG_MESSAGE_FORMAT;
2364                 }
2365                 break;
2366             case S_CCBS_INTERROGATE:
2367                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2368                 {
2369                   dbug(0,dprintf("format wrong"));
2370                   Info = _WRONG_MESSAGE_FORMAT;
2371                 }
2372                 break;
2373             default:
2374             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2375             {
2376               dbug(0,dprintf("format wrong"));
2377               Info = _WRONG_MESSAGE_FORMAT;
2378               break;
2379             }
2380                 break;
2381             }
2382
2383             if(Info) break;
2384             if((i=get_plci(a)))
2385             {
2386               rplci = &a->plci[i-1];
2387               switch(SSreq)
2388               {
2389                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2390                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2391                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2392                   break;
2393                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2394                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2395                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2396                   break;
2397                 case S_CALL_FORWARDING_STOP:
2398                   rplci->internal_command = CF_STOP_PEND;
2399                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400                   break;
2401                 case S_CCBS_REQUEST:
2402                   cai[1] = CCBS_REQUEST;
2403                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2404                   break;
2405                 case S_CCBS_DEACTIVATE:
2406                   cai[1] = CCBS_DEACTIVATE;
2407                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2408                   break;
2409                 case S_CCBS_INTERROGATE:
2410                   cai[1] = CCBS_INTERROGATE;
2411                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2412                   break;
2413                 default:
2414                   cai[1] = 0;
2415                 break;
2416               }
2417               rplci->appl = appl;
2418               rplci->number = Number;
2419               add_p(rplci,CAI,"\x01\x80");
2420               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2421               sig_req(rplci,ASSIGN,DSIG_ID);
2422               send_req(rplci);
2423             }
2424             else
2425             {
2426               Info = _OUT_OF_PLCI;
2427               break;
2428             }
2429
2430             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2431             switch(SSreq)
2432             {
2433             case S_INTERROGATE_NUMBERS:
2434                 cai[0] = 1;
2435                 add_p(rplci,CAI,cai);
2436                 break;
2437             case S_CCBS_REQUEST:
2438             case S_CCBS_DEACTIVATE:
2439                 cai[0] = 3;
2440                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2441                 add_p(rplci,CAI,cai);
2442                 break;
2443             case S_CCBS_INTERROGATE:
2444                 cai[0] = 3;
2445                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2446                 add_p(rplci,CAI,cai);
2447                 add_p(rplci,OAD,ss_parms[4].info);
2448                 break;
2449             default:
2450             cai[0] = 2;
2451             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2452             add_p(rplci,CAI,cai);
2453             add_p(rplci,OAD,ss_parms[5].info);
2454                 break;
2455             }
2456                         
2457             sig_req(rplci,S_SERVICE,0);
2458             send_req(rplci);
2459             return FALSE;
2460             break;
2461
2462           case S_MWI_ACTIVATE:
2463             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2464             {
2465               dbug(1,dprintf("format wrong"));
2466               Info = _WRONG_MESSAGE_FORMAT;
2467               break;
2468             }
2469             if(!plci)
2470             {                               
2471               if((i=get_plci(a)))
2472               {
2473                 rplci = &a->plci[i-1];
2474                 rplci->appl = appl;
2475                 rplci->cr_enquiry=TRUE;
2476                 add_p(rplci,CAI,"\x01\x80");
2477                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2478                 sig_req(rplci,ASSIGN,DSIG_ID);
2479                 send_req(rplci);
2480               }
2481               else
2482               {
2483                 Info = _OUT_OF_PLCI;
2484                 break;
2485               }
2486             }
2487             else
2488             {
2489               rplci = plci;
2490               rplci->cr_enquiry=FALSE;
2491             }
2492
2493             rplci->command = 0;
2494             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2495             rplci->appl = appl;
2496             rplci->number = Number;
2497
2498             cai[0] = 13;
2499             cai[1] = ACTIVATION_MWI; /* Function */
2500             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2501             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2502             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2503             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2504             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2505             add_p(rplci,CAI,cai);
2506             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2507             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2508             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2509             add_p(rplci,UID,ss_parms[10].info); /* Time */
2510             sig_req(rplci,S_SERVICE,0);
2511             send_req(rplci);
2512             return FALSE;
2513
2514           case S_MWI_DEACTIVATE:
2515             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2516             {
2517               dbug(1,dprintf("format wrong"));
2518               Info = _WRONG_MESSAGE_FORMAT;
2519               break;
2520             }
2521             if(!plci)
2522             {                               
2523               if((i=get_plci(a)))
2524               {
2525                 rplci = &a->plci[i-1];
2526                 rplci->appl = appl;
2527                 rplci->cr_enquiry=TRUE;
2528                 add_p(rplci,CAI,"\x01\x80");
2529                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2530                 sig_req(rplci,ASSIGN,DSIG_ID);
2531                 send_req(rplci);
2532               }
2533               else
2534               {
2535                 Info = _OUT_OF_PLCI;
2536                 break;
2537               }
2538             }
2539             else
2540             {
2541               rplci = plci;
2542               rplci->cr_enquiry=FALSE;
2543             }
2544
2545             rplci->command = 0;
2546             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2547             rplci->appl = appl;
2548             rplci->number = Number;
2549
2550             cai[0] = 5;
2551             cai[1] = DEACTIVATION_MWI; /* Function */
2552             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2553             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2554             add_p(rplci,CAI,cai);
2555             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2556             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2557             sig_req(rplci,S_SERVICE,0);
2558             send_req(rplci);
2559             return FALSE;
2560
2561           default:
2562             Info = 0x300E;  /* not supported */
2563             break;
2564         }
2565         break; /* case SELECTOR_SU_SERV: end */
2566
2567
2568       case SELECTOR_DTMF:
2569         return (dtmf_request (Id, Number, a, plci, appl, msg));
2570
2571
2572
2573       case SELECTOR_LINE_INTERCONNECT:
2574         return (mixer_request (Id, Number, a, plci, appl, msg));
2575
2576
2577
2578       case PRIV_SELECTOR_ECHO_CANCELLER:
2579         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2580         return (ec_request (Id, Number, a, plci, appl, msg));
2581
2582       case SELECTOR_ECHO_CANCELLER:
2583         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2584         return (ec_request (Id, Number, a, plci, appl, msg));
2585
2586
2587       case SELECTOR_V42BIS:
2588       default:
2589         Info = _FACILITY_NOT_SUPPORTED;
2590         break;
2591     } /* end of switch(selector) */
2592   }
2593
2594   dbug(1,dprintf("SendFacRc"));
2595   sendf(appl,
2596         _FACILITY_R|CONFIRM,
2597         Id,
2598         Number,
2599         "wws",Info,selector,SSparms);
2600   return FALSE;
2601 }
2602
2603 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
2604 {
2605   dbug(1,dprintf("facility_res"));
2606   return FALSE;
2607 }
2608
2609 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2610 {
2611   word Info = 0;
2612   byte req;
2613   byte len;
2614   word w;
2615   word fax_control_bits, fax_feature_bits, fax_info_change;
2616   API_PARSE * ncpi;
2617     byte pvc[2];
2618
2619     API_PARSE fax_parms[9];
2620   word i;
2621
2622
2623   dbug(1,dprintf("connect_b3_req"));
2624   if(plci)
2625   {
2626     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2627      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2628     {
2629       Info = _WRONG_STATE;
2630     }
2631     else
2632     {
2633       /* local reply if assign unsuccessfull
2634          or B3 protocol allows only one layer 3 connection
2635            and already connected
2636              or B2 protocol not any LAPD
2637                and connect_b3_req contradicts originate/answer direction */
2638       if (!plci->NL.Id
2639        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2640         && ((plci->channels != 0)
2641          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2642           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2643       {
2644         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2645                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2646         Info = _WRONG_STATE;
2647         sendf(appl,                                                        
2648               _CONNECT_B3_R|CONFIRM,
2649               Id,
2650               Number,
2651               "w",Info);
2652         return FALSE;
2653       }
2654       plci->requested_options_conn = 0;
2655
2656       req = N_CONNECT;
2657       ncpi = &parms[0];
2658       if(plci->B3_prot==2 || plci->B3_prot==3)
2659       {
2660         if(ncpi->length>2)
2661         {
2662           /* check for PVC */
2663           if(ncpi->info[2] || ncpi->info[3])
2664           {
2665             pvc[0] = ncpi->info[3];
2666             pvc[1] = ncpi->info[2];
2667             add_d(plci,2,pvc);
2668             req = N_RESET;
2669           }
2670           else
2671           {
2672             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2673             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2674           }
2675         }
2676       }
2677       else if(plci->B3_prot==5)
2678       {
2679         if (plci->NL.Id && !plci->nl_remove_id)
2680         {
2681           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2682           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2683           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2684            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2685           {
2686             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2687             fax_info_change = FALSE;
2688             if (ncpi->length >= 4)
2689             {
2690               w = GET_WORD(&ncpi->info[3]);
2691               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2692               {
2693                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2694                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2695                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2696                 fax_info_change = TRUE;
2697               }
2698               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2699               if (w & 0x0002)  /* Fax-polling request */
2700                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2701               if ((w & 0x0004) /* Request to send / poll another document */
2702                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2703               {
2704                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2705               }
2706               if (ncpi->length >= 6)
2707               {
2708                 w = GET_WORD(&ncpi->info[5]);
2709                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2710                 {
2711                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2712                   fax_info_change = TRUE;
2713                 }
2714
2715                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2716                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2717                 {
2718                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2719                 }
2720                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2721                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2722                 {
2723                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2724                 }
2725                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2726                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2727                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2728                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2729                 {
2730                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2731                     Info = _WRONG_MESSAGE_FORMAT;
2732                   else
2733                   {
2734                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2735                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2736       {
2737                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2738                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2739                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2740       }
2741                     w = fax_parms[4].length;
2742                     if (w > 20)
2743                       w = 20;
2744                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2745                     for (i = 0; i < w; i++)
2746                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2747                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2748                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2749                     w = fax_parms[5].length;
2750                     if (w > 20)
2751                       w = 20;
2752                     plci->fax_connect_info_buffer[len++] = (byte) w;
2753                     for (i = 0; i < w; i++)
2754                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2755                     w = fax_parms[6].length;
2756                     if (w > 20)
2757                       w = 20;
2758                     plci->fax_connect_info_buffer[len++] = (byte) w;
2759                     for (i = 0; i < w; i++)
2760                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2761                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2762                       & (1L << PRIVATE_FAX_NONSTANDARD))
2763       {
2764                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2765         {
2766                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2767                         plci->fax_connect_info_buffer[len++] = 0;
2768         }
2769                       else
2770                       {
2771           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2772             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2773    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2774           for (i = 0; i < fax_parms[7].length; i++)
2775      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2776                       }
2777                     }
2778                   }
2779                 }
2780                 else
2781                 {
2782                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2783                 }
2784                 fax_info_change = TRUE;
2785
2786               }
2787               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2788               {
2789                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2790                 fax_info_change = TRUE;
2791               }
2792             }
2793             if (Info == GOOD)
2794             {
2795               plci->fax_connect_info_length = len;
2796               if (fax_info_change)
2797               {
2798                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2799                 {
2800                   start_internal_command (Id, plci, fax_connect_info_command);
2801                   return FALSE;
2802                 }
2803                 else
2804                 {
2805                   start_internal_command (Id, plci, fax_adjust_b23_command);
2806                   return FALSE;
2807                 }
2808               }
2809             }
2810           }
2811           else  Info = _WRONG_STATE;
2812         }
2813         else  Info = _WRONG_STATE;
2814       }
2815
2816       else if (plci->B3_prot == B3_RTP)
2817       {
2818         plci->internal_req_buffer[0] = ncpi->length + 1;
2819         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2820         for (w = 0; w < ncpi->length; w++)
2821           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2822         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2823         return FALSE;
2824       }
2825
2826       if(!Info)
2827       {
2828         nl_req_ncci(plci,req,0);
2829         return 1;
2830       }
2831     }
2832   }
2833   else Info = _WRONG_IDENTIFIER;
2834
2835   sendf(appl,
2836         _CONNECT_B3_R|CONFIRM,
2837         Id,
2838         Number,
2839         "w",Info);
2840   return FALSE;
2841 }
2842
2843 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2844 {
2845   word ncci;
2846   API_PARSE * ncpi;
2847   byte req;
2848
2849   word w;
2850
2851
2852     API_PARSE fax_parms[9];
2853   word i;
2854   byte len;
2855
2856
2857   dbug(1,dprintf("connect_b3_res"));
2858
2859   ncci = (word)(Id>>16);
2860   if(plci && ncci) {
2861     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2862       if (GET_WORD (&parms[0].info[0]) != 0)
2863       {
2864         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2865         channel_request_xon (plci, a->ncci_ch[ncci]);
2866         channel_xmit_xon (plci);
2867         cleanup_ncci_data (plci, ncci);
2868         nl_req_ncci(plci,N_DISC,(byte)ncci);
2869         return 1;
2870       }
2871       a->ncci_state[ncci] = INC_ACT_PENDING;
2872
2873       req = N_CONNECT_ACK;
2874       ncpi = &parms[1];
2875       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2876       {
2877
2878         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2879           & (1L << PRIVATE_FAX_NONSTANDARD))
2880  {
2881    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2882     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2883     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2884    {
2885             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2886             if (plci->fax_connect_info_length < len)
2887             {
2888               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2889               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2890             }
2891             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2892             {
2893               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2894             }
2895             else
2896             {
2897               if (plci->fax_connect_info_length <= len)
2898                 plci->fax_connect_info_buffer[len] = 0;
2899               len += 1 + plci->fax_connect_info_buffer[len];
2900               if (plci->fax_connect_info_length <= len)
2901                 plci->fax_connect_info_buffer[len] = 0;
2902               len += 1 + plci->fax_connect_info_buffer[len];
2903               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2904                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2905               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2906               for (i = 0; i < fax_parms[7].length; i++)
2907                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2908             }
2909             plci->fax_connect_info_length = len;
2910             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2911             start_internal_command (Id, plci, fax_connect_ack_command);
2912      return FALSE;
2913           }
2914         }
2915
2916         nl_req_ncci(plci,req,(byte)ncci);
2917         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2918          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2919         {
2920           if (plci->B3_prot == 4)
2921             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2922           else
2923             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2924           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2925         }
2926       }
2927
2928       else if (plci->B3_prot == B3_RTP)
2929       {
2930         plci->internal_req_buffer[0] = ncpi->length + 1;
2931         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2932         for (w = 0; w < ncpi->length; w++)
2933           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2934         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2935         return FALSE;
2936       }
2937
2938       else
2939       {
2940         if(ncpi->length>2) {
2941           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2942           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2943         }
2944         nl_req_ncci(plci,req,(byte)ncci);
2945         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2946         if (plci->adjust_b_restore)
2947         {
2948           plci->adjust_b_restore = FALSE;
2949           start_internal_command (Id, plci, adjust_b_restore);
2950         }
2951       }
2952       return 1;
2953     }
2954   }
2955   return FALSE;
2956 }
2957
2958 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2959 {
2960   word ncci;
2961
2962   ncci = (word)(Id>>16);
2963   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2964
2965   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2966    && (plci->State != OUTG_DIS_PENDING))
2967   {
2968     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2969       a->ncci_state[ncci] = CONNECTED;
2970       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2971       channel_request_xon (plci, a->ncci_ch[ncci]);
2972       channel_xmit_xon (plci);
2973     }
2974   }
2975   return FALSE;
2976 }
2977
2978 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2979 {
2980   word Info;
2981   word ncci;
2982   API_PARSE * ncpi;
2983
2984   dbug(1,dprintf("disconnect_b3_req"));
2985
2986   Info = _WRONG_IDENTIFIER;
2987   ncci = (word)(Id>>16);
2988   if (plci && ncci)
2989   {
2990     Info = _WRONG_STATE;
2991     if ((a->ncci_state[ncci] == CONNECTED)
2992      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2993      || (a->ncci_state[ncci] == INC_CON_PENDING)
2994      || (a->ncci_state[ncci] == INC_ACT_PENDING))
2995     {
2996       a->ncci_state[ncci] = OUTG_DIS_PENDING;
2997       channel_request_xon (plci, a->ncci_ch[ncci]);
2998       channel_xmit_xon (plci);
2999
3000       if (a->ncci[ncci].data_pending
3001        && ((plci->B3_prot == B3_TRANSPARENT)
3002         || (plci->B3_prot == B3_T30)
3003         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3004       {
3005         plci->send_disc = (byte)ncci;
3006         plci->command = 0;
3007         return FALSE;
3008       }
3009       else
3010       {
3011         cleanup_ncci_data (plci, ncci);
3012
3013         if(plci->B3_prot==2 || plci->B3_prot==3)
3014         {
3015           ncpi = &parms[0];
3016           if(ncpi->length>3)
3017           {
3018             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3019           }
3020         }
3021         nl_req_ncci(plci,N_DISC,(byte)ncci);
3022       }
3023       return 1;
3024     }
3025   }
3026   sendf(appl,
3027         _DISCONNECT_B3_R|CONFIRM,
3028         Id,
3029         Number,
3030         "w",Info);
3031   return FALSE;
3032 }
3033
3034 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3035 {
3036   word ncci;
3037   word i;
3038
3039   ncci = (word)(Id>>16);
3040   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3041   if(plci && ncci) {
3042     plci->requested_options_conn = 0;
3043     plci->fax_connect_info_length = 0;
3044     plci->ncpi_state = 0x00;
3045     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3046       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3047     {
3048       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3049     }
3050     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3051     if(i<MAX_CHANNELS_PER_PLCI) {
3052       if(plci->channels)plci->channels--;
3053       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3054       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3055
3056       ncci_free_receive_buffers (plci, ncci);
3057
3058       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3059         if(plci->State == SUSPENDING){
3060           sendf(plci->appl,
3061                 _FACILITY_I,
3062                 Id & 0xffffL,
3063                 0,
3064                 "ws", (word)3, "\x03\x04\x00\x00");
3065           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3066         }
3067         plci_remove(plci);
3068         plci->State=IDLE;
3069       }
3070     }
3071     else
3072     {
3073       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3074        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3075        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3076       {
3077         ncci_free_receive_buffers (plci, ncci);
3078
3079         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3080
3081         plci->adapter->ncci_state[ncci] = IDLE;
3082         start_internal_command (Id, plci, fax_disconnect_command);
3083         return 1;
3084       }
3085     }
3086   }
3087   return FALSE;
3088 }
3089
3090 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3091 {
3092   NCCI   *ncci_ptr;
3093   DATA_B3_DESC   *data;
3094   word Info;
3095   word ncci;
3096   word i;
3097
3098   dbug(1,dprintf("data_b3_req"));
3099
3100   Info = _WRONG_IDENTIFIER;
3101   ncci = (word)(Id>>16);
3102   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3103
3104   if (plci && ncci)
3105   {
3106     Info = _WRONG_STATE;
3107     if ((a->ncci_state[ncci] == CONNECTED)
3108      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3109     {
3110         /* queue data */
3111       ncci_ptr = &(a->ncci[ncci]);
3112       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3113       if (i >= MAX_DATA_B3)
3114         i -= MAX_DATA_B3;
3115       data = &(ncci_ptr->DBuffer[i]);
3116       data->Number = Number;
3117       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3118        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3119       {
3120
3121         data->P = (byte   *)(*((dword   *)(parms[0].info)));
3122
3123       }
3124       else
3125         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3126       data->Length = GET_WORD(parms[1].info);
3127       data->Handle = GET_WORD(parms[2].info);
3128       data->Flags = GET_WORD(parms[3].info);
3129       (ncci_ptr->data_pending)++;
3130
3131         /* check for delivery confirmation */
3132       if (data->Flags & 0x0004)
3133       {
3134         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3135         if (i >= MAX_DATA_ACK)
3136           i -= MAX_DATA_ACK;
3137         ncci_ptr->DataAck[i].Number = data->Number;
3138         ncci_ptr->DataAck[i].Handle = data->Handle;
3139         (ncci_ptr->data_ack_pending)++;
3140       }
3141
3142       send_data(plci);
3143       return FALSE;
3144     }
3145   }
3146   if (appl)
3147   {
3148     if (plci)
3149     {
3150       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3151        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3152       {
3153
3154         TransmitBufferFree (appl, (byte   *)(*((dword   *)(parms[0].info))));
3155
3156       }
3157     }
3158     sendf(appl,
3159           _DATA_B3_R|CONFIRM,
3160           Id,
3161           Number,
3162           "ww",GET_WORD(parms[2].info),Info);
3163   }
3164   return FALSE;
3165 }
3166
3167 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3168 {
3169   word n;
3170   word ncci;
3171   word NCCIcode;
3172
3173   dbug(1,dprintf("data_b3_res"));
3174
3175   ncci = (word)(Id>>16);
3176   if(plci && ncci) {
3177     n = GET_WORD(parms[0].info);
3178     dbug(1,dprintf("free(%d)",n));
3179     NCCIcode = ncci | (((word) a->Id) << 8);
3180     if(n<appl->MaxBuffer &&
3181        appl->DataNCCI[n]==NCCIcode &&
3182        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3183       dbug(1,dprintf("found"));
3184       appl->DataNCCI[n] = 0;
3185
3186       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3187         channel_request_xon (plci, a->ncci_ch[ncci]);
3188       }
3189       channel_xmit_xon (plci);
3190
3191       if(appl->DataFlags[n] &4) {
3192         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3193         return 1;
3194       }
3195     }
3196   }
3197   return FALSE;
3198 }
3199
3200 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3201 {
3202   word Info;
3203   word ncci;
3204
3205   dbug(1,dprintf("reset_b3_req"));
3206
3207   Info = _WRONG_IDENTIFIER;
3208   ncci = (word)(Id>>16);
3209   if(plci && ncci)
3210   {
3211     Info = _WRONG_STATE;
3212     switch (plci->B3_prot)
3213     {
3214     case B3_ISO8208:
3215     case B3_X25_DCE:
3216       if(a->ncci_state[ncci]==CONNECTED)
3217       {
3218         nl_req_ncci(plci,N_RESET,(byte)ncci);
3219         send_req(plci);
3220         Info = GOOD;
3221       }
3222       break;
3223     case B3_TRANSPARENT:
3224       if(a->ncci_state[ncci]==CONNECTED)
3225       {
3226         start_internal_command (Id, plci, reset_b3_command);
3227         Info = GOOD;
3228       }
3229       break;
3230     }
3231   }
3232   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3233   sendf(appl,
3234         _RESET_B3_R|CONFIRM,
3235         Id,
3236         Number,
3237         "w",Info);
3238   return FALSE;
3239 }
3240
3241 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3242 {
3243   word ncci;
3244
3245   dbug(1,dprintf("reset_b3_res"));
3246
3247   ncci = (word)(Id>>16);
3248   if(plci && ncci) {
3249     switch (plci->B3_prot)
3250     {
3251     case B3_ISO8208:
3252     case B3_X25_DCE:
3253       if(a->ncci_state[ncci]==INC_RES_PENDING)
3254       {
3255         a->ncci_state[ncci] = CONNECTED;
3256         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3257         return TRUE;
3258       }
3259     break;
3260     }
3261   }
3262   return FALSE;
3263 }
3264
3265 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3266 {
3267   word ncci;
3268   API_PARSE * ncpi;
3269   byte req;
3270
3271   dbug(1,dprintf("connect_b3_t90_a_res"));
3272
3273   ncci = (word)(Id>>16);
3274   if(plci && ncci) {
3275     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3276       a->ncci_state[ncci] = CONNECTED;
3277     }
3278     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3279       a->ncci_state[ncci] = CONNECTED;
3280
3281       req = N_CONNECT_ACK;
3282
3283         /* parms[0]==0 for CAPI original message definition! */
3284       if(parms[0].info) {
3285         ncpi = &parms[1];
3286         if(ncpi->length>2) {
3287           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3288           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3289         }
3290       }
3291       nl_req_ncci(plci,req,(byte)ncci);
3292       return 1;
3293     }
3294   }
3295   return FALSE;
3296 }
3297
3298
3299 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3300 {
3301   word Info=0;
3302   word i;
3303   byte tel;
3304     API_PARSE bp_parms[7];
3305
3306   if(!plci || !msg)
3307   {
3308     Info = _WRONG_IDENTIFIER;
3309   }
3310   else
3311   {
3312     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3313                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3314     dbug(1,dprintf("PlciState=0x%x",plci->State));
3315     for(i=0;i<7;i++) bp_parms[i].length = 0;
3316
3317     /* check if no channel is open, no B3 connected only */
3318     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3319      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3320     {
3321       Info = _WRONG_STATE;
3322     }
3323     /* check message format and fill bp_parms pointer */
3324     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3325     {
3326       Info = _WRONG_MESSAGE_FORMAT;
3327     }
3328     else
3329     {
3330       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3331       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3332         if(Id & EXT_CONTROLLER)
3333         {
3334           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3335           return 0;
3336         }
3337         plci->State=INC_CON_CONNECTED_ALERT;
3338         plci->appl = appl;
3339         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3340         dump_c_ind_mask (plci);
3341         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3342         {                         /* its quasi a connect        */
3343           if(test_c_ind_mask_bit (plci, i))
3344             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3345         }
3346       }
3347
3348       api_save_msg(msg, "s", &plci->saved_msg);
3349       tel = plci->tel;
3350       if(Id & EXT_CONTROLLER)
3351       {
3352         if(tel) /* external controller in use by this PLCI */
3353         {
3354           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3355           {
3356             dbug(1,dprintf("Ext_Ctrl in use 1"));
3357             Info = _WRONG_STATE;
3358           }
3359         }
3360         else  /* external controller NOT in use by this PLCI ? */
3361         {
3362           if(a->AdvSignalPLCI)
3363           {
3364             dbug(1,dprintf("Ext_Ctrl in use 2"));
3365             Info = _WRONG_STATE;
3366           }
3367           else /* activate the codec */
3368           {
3369             dbug(1,dprintf("Ext_Ctrl start"));
3370             if(AdvCodecSupport(a, plci, appl, 0) )
3371             {
3372               dbug(1,dprintf("Error in codec procedures"));
3373               Info = _WRONG_STATE;
3374             }
3375             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3376             {
3377               plci->spoofed_msg = AWAITING_SELECT_B;
3378               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3379               plci->command = 0;
3380               dbug(1,dprintf("continue if codec loaded"));
3381               return FALSE;
3382             }
3383           }
3384         }
3385       }
3386       else /* external controller bit is OFF */
3387       {
3388         if(tel) /* external controller in use, need to switch off */
3389         {
3390           if(a->AdvSignalAppl==appl)
3391           {
3392             CodecIdCheck(a, plci);
3393             plci->tel = 0;
3394             plci->adv_nl = 0;
3395             dbug(1,dprintf("Ext_Ctrl disable"));
3396           }
3397           else
3398           {
3399             dbug(1,dprintf("Ext_Ctrl not requested"));
3400           }
3401         }
3402       }
3403       if (!Info)
3404       {
3405         if (plci->call_dir & CALL_DIR_OUT)
3406           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3407         else if (plci->call_dir & CALL_DIR_IN)
3408           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3409         start_internal_command (Id, plci, select_b_command);
3410         return FALSE;
3411       }
3412     }
3413   }
3414   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3415   return FALSE;
3416 }
3417
3418 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3419 {
3420   word command;
3421   word i;
3422   word ncci;
3423   API_PARSE * m;
3424     API_PARSE m_parms[5];
3425   word codec;
3426   byte req;
3427   byte ch;
3428   byte dir;
3429   static byte chi[2] = {0x01,0x00};
3430   static byte lli[2] = {0x01,0x00};
3431   static byte codec_cai[2] = {0x01,0x01};
3432   static byte null_msg = {0};
3433   static API_PARSE null_parms = { 0, &null_msg };
3434   PLCI   * v_plci;
3435   word Info=0;
3436
3437   dbug(1,dprintf("manufacturer_req"));
3438   for(i=0;i<5;i++) m_parms[i].length = 0;
3439
3440   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441     Info = _WRONG_MESSAGE_FORMAT;
3442   }
3443   command = GET_WORD(parms[1].info);
3444   m = &parms[2];
3445   if (!Info)
3446   {
3447     switch(command) {
3448     case _DI_ASSIGN_PLCI:
3449       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450         Info = _WRONG_MESSAGE_FORMAT;
3451         break;
3452       }
3453       codec = GET_WORD(m_parms[0].info);
3454       ch = m_parms[1].info[0];
3455       dir = m_parms[2].info[0];
3456       if((i=get_plci(a))) {
3457         plci = &a->plci[i-1];
3458         plci->appl = appl;
3459         plci->command = _MANUFACTURER_R;
3460         plci->m_command = command;
3461         plci->number = Number;
3462         plci->State = LOCAL_CONNECT;
3463         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3465
3466         if((ch==1 || ch==2) && (dir<=2)) {
3467           chi[1] = (byte)(0x80|ch);
3468           lli[1] = 0;
3469           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470           switch(codec)
3471           {
3472           case 0:
3473             Info = add_b1(plci,&m_parms[3],0,0);
3474             break;
3475           case 1:
3476             add_p(plci,CAI,codec_cai);
3477             break;
3478           /* manual 'swich on' to the codec support without signalling */
3479           /* first 'assign plci' with this function, then use */
3480           case 2:
3481             if(AdvCodecSupport(a, plci, appl, 0) ) {
3482               Info = _RESOURCE_ERROR;
3483             }
3484             else {
3485               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486               lli[1] = 0x10; /* local call codec stream */
3487             }
3488             break;
3489           }
3490
3491           plci->State = LOCAL_CONNECT;
3492           plci->manufacturer = TRUE;
3493           plci->command = _MANUFACTURER_R;
3494           plci->m_command = command;
3495           plci->number = Number;
3496
3497           if(!Info)
3498           {
3499             add_p(plci,LLI,lli);
3500             add_p(plci,CHI,chi);
3501             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502             sig_req(plci,ASSIGN,DSIG_ID);
3503
3504             if(!codec)
3505             {
3506               Info = add_b23(plci,&m_parms[3]);
3507               if(!Info)
3508               {
3509                 nl_req_ncci(plci,ASSIGN,0);
3510                 send_req(plci);
3511               }
3512             }
3513             if(!Info)
3514             {
3515               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3517               {
3518                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519                 plci->spoofed_msg = AWAITING_MANUF_CON;
3520                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521                 plci->command = 0;
3522                 send_req(plci);
3523                 return FALSE;
3524               }
3525               if(dir==1) {
3526                 sig_req(plci,CALL_REQ,0);
3527               }
3528               else if(!dir){
3529                 sig_req(plci,LISTEN_REQ,0);
3530               }
3531               send_req(plci);
3532             }
3533             else
3534             {
3535               sendf(appl,
3536                     _MANUFACTURER_R|CONFIRM,
3537                     Id,
3538                     Number,
3539                     "dww",_DI_MANU_ID,command,Info);
3540               return 2;
3541             }
3542           }
3543         }
3544       }
3545       else  Info = _OUT_OF_PLCI;
3546       break;
3547
3548     case _DI_IDI_CTRL:
3549       if(!plci)
3550       {
3551         Info = _WRONG_IDENTIFIER;
3552         break;
3553       }
3554       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555         Info = _WRONG_MESSAGE_FORMAT;
3556         break;
3557       }
3558       req = m_parms[0].info[0];
3559       plci->command = _MANUFACTURER_R;
3560       plci->m_command = command;
3561       plci->number = Number;
3562       if(req==CALL_REQ)
3563       {
3564         plci->b_channel = getChannel(&m_parms[1]);
3565         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3567         {
3568           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570           plci->command = 0;
3571           break;
3572         }
3573       }
3574       else if(req==LAW_REQ)
3575       {
3576         plci->cr_enquiry = TRUE;
3577       }
3578       add_ss(plci,FTY,&m_parms[1]);
3579       sig_req(plci,req,0);
3580       send_req(plci);
3581       if(req==HANGUP)
3582       {      
3583         if (plci->NL.Id && !plci->nl_remove_id)
3584         {
3585           if (plci->channels)
3586           {
3587             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3588             {
3589               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3590               {
3591                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592                 cleanup_ncci_data (plci, ncci);
3593                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3594               }
3595             }
3596           }
3597           mixer_remove (plci);
3598           nl_req_ncci(plci,REMOVE,0);
3599           send_req(plci);
3600         }  
3601       }
3602       break;
3603
3604     case _DI_SIG_CTRL:
3605     /* signalling control for loop activation B-channel */
3606       if(!plci)
3607       {
3608         Info = _WRONG_IDENTIFIER;
3609         break;
3610       }
3611       if(m->length){
3612         plci->command = _MANUFACTURER_R;
3613         plci->number = Number;
3614         add_ss(plci,FTY,m);
3615         sig_req(plci,SIG_CTRL,0);
3616         send_req(plci);
3617       }
3618       else Info = _WRONG_MESSAGE_FORMAT;
3619       break;
3620
3621     case _DI_RXT_CTRL:
3622     /* activation control for receiver/transmitter B-channel */
3623       if(!plci)
3624       {
3625         Info = _WRONG_IDENTIFIER;
3626         break;
3627       }
3628       if(m->length){
3629         plci->command = _MANUFACTURER_R;
3630         plci->number = Number;
3631         add_ss(plci,FTY,m);
3632         sig_req(plci,DSP_CTRL,0);
3633         send_req(plci);
3634       }
3635       else Info = _WRONG_MESSAGE_FORMAT;
3636       break;
3637
3638     case _DI_ADV_CODEC:
3639     case _DI_DSP_CTRL:
3640       /* TEL_CTRL commands to support non standard adjustments: */
3641       /* Ring on/off, Handset micro volume, external micro vol. */
3642       /* handset+external speaker volume, receiver+transm. gain,*/
3643       /* handsfree on (hookinfo off), set mixer command         */
3644
3645       if(command == _DI_ADV_CODEC)
3646       {
3647         if(!a->AdvCodecPLCI) {
3648           Info = _WRONG_STATE;
3649           break;
3650         }
3651         v_plci = a->AdvCodecPLCI;
3652       }
3653       else
3654       {
3655         if (plci
3656          && (m->length >= 3)
3657          && (m->info[1] == 0x1c)
3658          && (m->info[2] >= 1))
3659         {
3660           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3661           {
3662             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3663             {
3664               Info = _WRONG_STATE;
3665               break;
3666             }
3667             a->adv_voice_coef_length = m->info[2] - 1;
3668             if (a->adv_voice_coef_length > m->length - 3)
3669               a->adv_voice_coef_length = (byte)(m->length - 3);
3670             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672             for (i = 0; i < a->adv_voice_coef_length; i++)
3673               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674             if (plci->B1_facilities & B1_FACILITY_VOICE)
3675               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676             break;
3677           }
3678           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3679           {
3680             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3681             {
3682               Info = _FACILITY_NOT_SUPPORTED;
3683               break;
3684             }
3685
3686             plci->dtmf_parameter_length = m->info[2] - 1;
3687             if (plci->dtmf_parameter_length > m->length - 3)
3688               plci->dtmf_parameter_length = (byte)(m->length - 3);
3689             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691             for (i = 0; i < plci->dtmf_parameter_length; i++)
3692               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694               dtmf_parameter_write (plci);
3695             break;
3696
3697           }
3698         }
3699         v_plci = plci;
3700       }
3701
3702       if(!v_plci)
3703       {
3704         Info = _WRONG_IDENTIFIER;
3705         break;
3706       }
3707       if(m->length){
3708         add_ss(v_plci,FTY,m);
3709         sig_req(v_plci,TEL_CTRL,0);
3710         send_req(v_plci);
3711       }
3712       else Info = _WRONG_MESSAGE_FORMAT;
3713
3714       break;
3715
3716     case _DI_OPTIONS_REQUEST:
3717       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718         Info = _WRONG_MESSAGE_FORMAT;
3719         break;
3720       }
3721       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3722       {
3723         Info = _FACILITY_NOT_SUPPORTED;
3724         break;
3725       }
3726       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727       break;
3728
3729
3730
3731     default:
3732       Info = _WRONG_MESSAGE_FORMAT;
3733       break;
3734     }
3735   }
3736
3737   sendf(appl,
3738         _MANUFACTURER_R|CONFIRM,
3739         Id,
3740         Number,
3741         "dww",_DI_MANU_ID,command,Info);
3742   return FALSE;
3743 }
3744
3745
3746 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3747 {
3748   word indication;
3749
3750     API_PARSE m_parms[3];
3751   API_PARSE *ncpi;
3752     API_PARSE fax_parms[9];
3753   word i;
3754   byte len;
3755
3756
3757   dbug(1,dprintf("manufacturer_res"));
3758
3759   if ((msg[0].length == 0)
3760    || (msg[1].length == 0)
3761    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3762   {
3763     return FALSE;
3764   }
3765   indication = GET_WORD(msg[1].info);
3766   switch (indication)
3767   {
3768
3769   case _DI_NEGOTIATE_B3:
3770     if(!plci)
3771       break;
3772     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3773      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3774     {
3775       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3776       break;
3777     }
3778     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3779     {
3780       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3781       break;
3782     }
3783     ncpi = &m_parms[1];
3784     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3785     if (plci->fax_connect_info_length < len)
3786     {
3787       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3788       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3789     }
3790     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3791     {
3792       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3793     }
3794     else
3795     {
3796       if (plci->fax_connect_info_length <= len)
3797         plci->fax_connect_info_buffer[len] = 0;
3798       len += 1 + plci->fax_connect_info_buffer[len];
3799       if (plci->fax_connect_info_length <= len)
3800         plci->fax_connect_info_buffer[len] = 0;
3801       len += 1 + plci->fax_connect_info_buffer[len];
3802       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3803         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3804       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3805       for (i = 0; i < fax_parms[7].length; i++)
3806         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3807     }
3808     plci->fax_connect_info_length = len;
3809     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3810     start_internal_command (Id, plci, fax_edata_ack_command);
3811     break;
3812
3813   }
3814   return FALSE;
3815 }
3816
3817 /*------------------------------------------------------------------*/
3818 /* IDI callback function                                            */
3819 /*------------------------------------------------------------------*/
3820
3821 void   callback(ENTITY   * e)
3822 {
3823   DIVA_CAPI_ADAPTER   * a;
3824   APPL   * appl;
3825   PLCI   * plci;
3826   CAPI_MSG   *m;
3827   word i, j;
3828   byte rc;
3829   byte ch;
3830   byte req;
3831   byte global_req;
3832   int no_cancel_rc;
3833
3834   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3835                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3836
3837   a = &(adapter[(byte)e->user[0]]);
3838   plci = &(a->plci[e->user[1]]);
3839   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3840
3841   /*
3842      If new protocol code and new XDI is used then CAPI should work
3843      fully in accordance with IDI cpec an look on callback field instead
3844      of Rc field for return codes.
3845    */
3846   if (((e->complete == 0xff) && no_cancel_rc) ||
3847       (e->Rc && !no_cancel_rc)) {
3848     rc = e->Rc;
3849     ch = e->RcCh;
3850     req = e->Req;
3851     e->Rc = 0;
3852
3853     if (e->user[0] & 0x8000)
3854     {
3855       /*
3856          If REMOVE request was sent then we have to wait until
3857          return code with Id set to zero arrives.
3858          All other return codes should be ignored.
3859          */
3860       if (req == REMOVE)
3861       {
3862         if (e->Id)
3863         {
3864           dbug(1,dprintf("cancel RC in REMOVE state"));
3865           return;
3866         }
3867         channel_flow_control_remove (plci);
3868         for (i = 0; i < 256; i++)
3869         {
3870           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3871             a->FlowControlIdTable[i] = 0;
3872         }
3873         plci->nl_remove_id = 0;
3874         if (plci->rx_dma_descriptor > 0) {
3875           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3876           plci->rx_dma_descriptor = 0;
3877         }
3878       }
3879       if (rc == OK_FC)
3880       {
3881         a->FlowControlIdTable[ch] = e->Id;
3882         a->FlowControlSkipTable[ch] = 0;
3883
3884         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3885         a->ch_flow_plci[ch] = plci->Id;
3886         plci->nl_req = 0;
3887       }
3888       else
3889       {
3890         /*
3891           Cancel return codes self, if feature was requested
3892           */
3893         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3894           a->FlowControlIdTable[ch] = 0;
3895           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3896             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3897             return;
3898           }
3899         }
3900
3901         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3902         {
3903           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3904           if (ch == e->ReqCh)
3905             plci->nl_req = 0;
3906         }
3907         else
3908           plci->nl_req = 0;
3909       }
3910       if (plci->nl_req)
3911         control_rc (plci, 0, rc, ch, 0, TRUE);
3912       else
3913       {
3914         if (req == N_XON)
3915         {
3916           channel_x_on (plci, ch);
3917           if (plci->internal_command)
3918             control_rc (plci, req, rc, ch, 0, TRUE);
3919         }
3920         else
3921         {
3922           if (plci->nl_global_req)
3923           {
3924             global_req = plci->nl_global_req;
3925             plci->nl_global_req = 0;
3926             if (rc != ASSIGN_OK) {
3927               e->Id = 0;
3928               if (plci->rx_dma_descriptor > 0) {
3929                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3930                 plci->rx_dma_descriptor = 0;
3931               }
3932             }
3933             channel_xmit_xon (plci);
3934             control_rc (plci, 0, rc, ch, global_req, TRUE);
3935           }
3936           else if (plci->data_sent)
3937           {
3938             channel_xmit_xon (plci);
3939             plci->data_sent = FALSE;
3940             plci->NL.XNum = 1;
3941             data_rc (plci, ch);
3942             if (plci->internal_command)
3943               control_rc (plci, req, rc, ch, 0, TRUE);
3944           }
3945           else
3946           {
3947             channel_xmit_xon (plci);
3948             control_rc (plci, req, rc, ch, 0, TRUE);
3949           }
3950         }
3951       }
3952     }
3953     else
3954     {
3955       /*
3956          If REMOVE request was sent then we have to wait until
3957          return code with Id set to zero arrives.
3958          All other return codes should be ignored.
3959          */
3960       if (req == REMOVE)
3961       {
3962         if (e->Id)
3963         {
3964           dbug(1,dprintf("cancel RC in REMOVE state"));
3965           return;
3966         }
3967         plci->sig_remove_id = 0;
3968       }
3969       plci->sig_req = 0;
3970       if (plci->sig_global_req)
3971       {
3972         global_req = plci->sig_global_req;
3973         plci->sig_global_req = 0;
3974         if (rc != ASSIGN_OK)
3975           e->Id = 0;
3976         channel_xmit_xon (plci);
3977         control_rc (plci, 0, rc, ch, global_req, FALSE);
3978       }
3979       else
3980       {
3981         channel_xmit_xon (plci);
3982         control_rc (plci, req, rc, ch, 0, FALSE);
3983       }
3984     }
3985     /*
3986       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3987       same callback. Also if new XDI and protocol code used then jump
3988       direct to finish.
3989       */
3990     if (no_cancel_rc) {
3991       channel_xmit_xon(plci);
3992       goto capi_callback_suffix;
3993     }
3994   }
3995
3996   channel_xmit_xon(plci);
3997
3998   if (e->Ind) {
3999     if (e->user[0] &0x8000) {
4000       byte Ind = e->Ind & 0x0f;
4001       byte Ch = e->IndCh;
4002       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4003           (a->ch_flow_plci[Ch] == plci->Id)) {
4004         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4005           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4006         }
4007         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4008       }
4009       nl_ind(plci);
4010       if ((e->RNR != 1) &&
4011           (a->ch_flow_plci[Ch] == plci->Id) &&
4012           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4013         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4014         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4015       }
4016     } else {
4017       sig_ind(plci);
4018     }
4019     e->Ind = 0;
4020   }
4021
4022 capi_callback_suffix:
4023
4024   while (!plci->req_in
4025    && !plci->internal_command
4026    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4027   {
4028     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4029
4030     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4031
4032     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4033     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4034     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4035       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4036     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4037     {
4038       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4039       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4040     }
4041     else
4042     {
4043       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4044     }
4045     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4046     {
4047       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4048       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4049     }
4050     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4051     {
4052       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4053       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4054     }
4055     i = api_put (appl, m);
4056     if (i != 0)
4057     {
4058       if (m->header.command == _DATA_B3_R)
4059
4060         TransmitBufferFree (appl, (byte   *)(m->info.data_b3_req.Data));
4061
4062       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4063       break;
4064     }
4065
4066     if (plci->li_notify_update)
4067     {
4068       plci->li_notify_update = FALSE;
4069       mixer_notify_update (plci, FALSE);
4070     }
4071
4072   }
4073   send_data(plci);
4074   send_req(plci);
4075 }
4076
4077
4078 void control_rc(PLCI   * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4079 {
4080   dword Id;
4081   dword rId;
4082   word Number;
4083   word Info=0;
4084   word i;
4085   word ncci;
4086   DIVA_CAPI_ADAPTER   * a;
4087   APPL   * appl;
4088   PLCI   * rplci;
4089     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4090     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4091
4092   if (!plci) {
4093     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4094     return;
4095   }
4096   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4097   if(plci->req_in!=plci->req_out)
4098   {
4099     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4100     {
4101       dbug(1,dprintf("req_1return"));
4102       return;
4103     }
4104     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4105   }
4106   plci->req_in = plci->req_in_start = plci->req_out = 0;
4107   dbug(1,dprintf("control_rc"));
4108
4109   appl = plci->appl;
4110   a = plci->adapter;
4111   ncci = a->ch_ncci[ch];
4112   if(appl)
4113   {
4114     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4115     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4116     Number = plci->number;
4117     dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command));
4118     dbug(1,dprintf("channels=0x%x",plci->channels));
4119     if (plci_remove_check(plci))
4120       return;
4121     if(req==REMOVE && rc==ASSIGN_OK)
4122     {
4123       sig_req(plci,HANGUP,0);
4124       sig_req(plci,REMOVE,0);
4125       send_req(plci);
4126     }
4127     if(plci->command)
4128     {
4129       switch(plci->command)
4130       {
4131       case C_HOLD_REQ:
4132         dbug(1,dprintf("HoldRC=0x%x",rc));
4133         SSparms[1] = (byte)S_HOLD;
4134         if(rc!=OK)
4135         {
4136           plci->SuppState = IDLE;
4137           Info = 0x2001;
4138         }
4139         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4140         break;
4141
4142       case C_RETRIEVE_REQ:
4143         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4144         SSparms[1] = (byte)S_RETRIEVE;
4145         if(rc!=OK)
4146         {
4147           plci->SuppState = CALL_HELD;
4148           Info = 0x2001;
4149         }
4150         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4151         break;
4152
4153       case _INFO_R:
4154         dbug(1,dprintf("InfoRC=0x%x",rc));
4155         if(rc!=OK) Info=_WRONG_STATE;
4156         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4157         break;
4158
4159       case _CONNECT_R:
4160         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4161         if (plci->State == INC_DIS_PENDING)
4162           break;
4163         if(plci->Sig.Id!=0xff)
4164         {
4165           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4166            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4167           {
4168             dbug(1,dprintf("No more IDs/Call_Req failed"));
4169             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4170             plci_remove(plci);
4171             plci->State = IDLE;
4172             break;
4173           }
4174           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4175           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4176         }
4177         else /* D-ch activation */
4178         {
4179           if (rc != ASSIGN_OK)
4180           {
4181             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4182             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4183             plci_remove(plci);
4184             plci->State = IDLE;
4185             break;
4186           }
4187           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4188           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4189           plci->State = INC_ACT_PENDING;
4190         }
4191         break;
4192
4193       case _CONNECT_I|RESPONSE:
4194         if (plci->State != INC_DIS_PENDING)
4195           plci->State = INC_CON_ACCEPT;
4196         break;
4197
4198       case _DISCONNECT_R:
4199         if (plci->State == INC_DIS_PENDING)
4200           break;
4201         if(plci->Sig.Id!=0xff)
4202         {
4203           plci->State = OUTG_DIS_PENDING;
4204           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4205         }
4206         break;
4207
4208       case SUSPEND_REQ:
4209         break;
4210
4211       case RESUME_REQ:
4212         break;
4213
4214       case _CONNECT_B3_R:
4215         if(rc!=OK)
4216         {
4217           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4218           break;
4219         }
4220         ncci = get_ncci (plci, ch, 0);
4221         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4222         plci->channels++;
4223         if(req==N_RESET)
4224         {
4225           a->ncci_state[ncci] = INC_ACT_PENDING;
4226           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4227           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4228         }
4229         else
4230         {
4231           a->ncci_state[ncci] = OUTG_CON_PENDING;
4232           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4233         }
4234         break;
4235
4236       case _CONNECT_B3_I|RESPONSE:
4237         break;
4238
4239       case _RESET_B3_R:
4240 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4241         break;
4242
4243       case _DISCONNECT_B3_R:
4244         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4245         break;
4246
4247       case _MANUFACTURER_R:
4248         break;
4249
4250       case PERM_LIST_REQ:
4251         if(rc!=OK)
4252         {
4253           Info = _WRONG_IDENTIFIER;
4254           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4255           plci_remove(plci);
4256         }
4257         else
4258           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4259         break;
4260
4261       default:
4262         break;
4263       }
4264       plci->command = 0;
4265     }
4266     else if (plci->internal_command)
4267     {
4268       switch(plci->internal_command)
4269       {
4270       case BLOCK_PLCI:
4271         return;
4272
4273       case GET_MWI_STATE:
4274         if(rc==OK) /* command supported, wait for indication */
4275         {
4276           return;
4277         }
4278         plci_remove(plci);
4279         break;
4280
4281         /* Get Supported Services */
4282       case GETSERV_REQ_PEND:
4283         if(rc==OK) /* command supported, wait for indication */
4284         {
4285           break;
4286         }
4287         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4288         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4289         plci_remove(plci);
4290         break;
4291
4292       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4293       case INTERR_NUMBERS_REQ_PEND:
4294       case CF_START_PEND:                  /* Call Forwarding Start pending */
4295       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4296       case CCBS_REQUEST_REQ_PEND:
4297       case CCBS_DEACTIVATE_REQ_PEND:
4298       case CCBS_INTERROGATE_REQ_PEND:
4299         switch(plci->internal_command)
4300         {
4301           case INTERR_DIVERSION_REQ_PEND:
4302             SSparms[1] = S_INTERROGATE_DIVERSION;
4303             break;
4304           case INTERR_NUMBERS_REQ_PEND:
4305             SSparms[1] = S_INTERROGATE_NUMBERS;
4306             break;
4307           case CF_START_PEND:
4308             SSparms[1] = S_CALL_FORWARDING_START;
4309             break;
4310           case CF_STOP_PEND:
4311             SSparms[1] = S_CALL_FORWARDING_STOP;
4312             break;
4313           case CCBS_REQUEST_REQ_PEND:
4314             SSparms[1] = S_CCBS_REQUEST;
4315             break;
4316           case CCBS_DEACTIVATE_REQ_PEND:
4317             SSparms[1] = S_CCBS_DEACTIVATE;
4318             break;
4319           case CCBS_INTERROGATE_REQ_PEND:
4320             SSparms[1] = S_CCBS_INTERROGATE;
4321             break;
4322         }
4323         if(global_req==ASSIGN)
4324         {
4325           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4326           return;
4327         }
4328         if(!plci->appl) break;
4329         if(rc==ISDN_GUARD_REJ)
4330         {
4331           Info = _CAPI_GUARD_ERROR;
4332         }
4333         else if(rc!=OK)
4334         {
4335           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4336         }
4337         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4338               plci->number,"wws",Info,(word)3,SSparms);
4339         if(Info) plci_remove(plci);
4340         break;
4341
4342         /* 3pty conference pending */
4343       case PTY_REQ_PEND:
4344         if(!plci->relatedPTYPLCI) break;
4345         rplci = plci->relatedPTYPLCI;
4346         SSparms[1] = plci->ptyState;
4347         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4348         if(rplci->tel) rId|=EXT_CONTROLLER;
4349         if(rc!=OK)
4350         {
4351           Info = 0x300E; /* not supported */
4352           plci->relatedPTYPLCI = NULL;
4353           plci->ptyState = 0;
4354         }
4355         sendf(rplci->appl,
4356               _FACILITY_R|CONFIRM,
4357               rId,
4358               plci->number,
4359               "wws",Info,(word)3,SSparms);
4360         break;
4361
4362         /* Explicit Call Transfer pending */
4363       case ECT_REQ_PEND:
4364         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4365         if(!plci->relatedPTYPLCI) break;
4366         rplci = plci->relatedPTYPLCI;
4367         SSparms[1] = S_ECT;
4368         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4369         if(rplci->tel) rId|=EXT_CONTROLLER;
4370         if(rc!=OK)
4371         {
4372           Info = 0x300E; /* not supported */
4373           plci->relatedPTYPLCI = NULL;
4374           plci->ptyState = 0;
4375         }
4376         sendf(rplci->appl,
4377               _FACILITY_R|CONFIRM,
4378               rId,
4379               plci->number,
4380               "wws",Info,(word)3,SSparms);
4381         break;
4382
4383       case _MANUFACTURER_R:
4384         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4385         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4386         {
4387           dbug(1,dprintf("No more IDs"));
4388           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4389           plci_remove(plci);  /* after codec init, internal codec commands pending */
4390         }
4391         break;
4392
4393       case _CONNECT_R:
4394         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4395         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4396         {
4397           dbug(1,dprintf("No more IDs"));
4398           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4399           plci_remove(plci);  /* after codec init, internal codec commands pending */
4400         }
4401         break;
4402
4403       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4404         return;
4405
4406       case PERM_COD_CALL:
4407         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4408         plci->internal_command = PERM_COD_CONN_PEND;
4409         return;
4410
4411       case PERM_COD_ASSIGN:
4412         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4413         if(rc!=ASSIGN_OK) break;
4414         sig_req(plci,CALL_REQ,0);
4415         send_req(plci);
4416         plci->internal_command = PERM_COD_CALL;
4417         return;
4418
4419         /* Null Call Reference Request pending */
4420       case C_NCR_FAC_REQ:
4421         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4422         if(global_req==ASSIGN)
4423         {
4424           if(rc==ASSIGN_OK)
4425           {
4426             return;
4427           }
4428           else
4429           {
4430             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4431             appl->NullCREnable = FALSE;
4432             plci_remove(plci);
4433           }
4434         }
4435         else if(req==NCR_FACILITY)
4436         {
4437           if(rc==OK)
4438           {
4439             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4440           }
4441           else
4442           {
4443             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4444             appl->NullCREnable = FALSE;
4445           }
4446           plci_remove(plci);
4447         }
4448         break;
4449
4450       case HOOK_ON_REQ:
4451         if(plci->channels)
4452         {
4453           if(a->ncci_state[ncci]==CONNECTED)
4454           {
4455             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4456             cleanup_ncci_data (plci, ncci);
4457             nl_req_ncci(plci,N_DISC,(byte)ncci);
4458           }
4459           break;
4460         }
4461         break;
4462
4463       case HOOK_OFF_REQ:
4464         if (plci->State == INC_DIS_PENDING)
4465           break;
4466         sig_req(plci,CALL_REQ,0);
4467         send_req(plci);
4468         plci->State=OUTG_CON_PENDING;
4469         break;
4470
4471
4472       case MWI_ACTIVATE_REQ_PEND:
4473       case MWI_DEACTIVATE_REQ_PEND:
4474         if(global_req == ASSIGN && rc==ASSIGN_OK)
4475         {
4476           dbug(1,dprintf("MWI_REQ assigned"));
4477           return;
4478         }
4479         else if(rc!=OK)
4480         {                 
4481           if(rc==WRONG_IE)
4482           {
4483             Info = 0x2007; /* Illegal message parameter coding */
4484             dbug(1,dprintf("MWI_REQ invalid parameter"));
4485           }
4486           else
4487           {
4488             Info = 0x300B; /* not supported */                      
4489             dbug(1,dprintf("MWI_REQ not supported"));
4490           }
4491           /* 0x3010: Request not allowed in this state */
4492           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4493                     
4494         }
4495         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4496         {
4497           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4498         }
4499         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4500
4501         if(plci->cr_enquiry)
4502         {
4503           sendf(plci->appl,
4504                 _FACILITY_R|CONFIRM,
4505                 Id&0xf,
4506                 plci->number,
4507                 "wws",Info,(word)3,SSparms);
4508           if(rc!=OK) plci_remove(plci);
4509         }
4510         else
4511         {
4512           sendf(plci->appl,
4513                 _FACILITY_R|CONFIRM,
4514                 Id,
4515                 plci->number,
4516                 "wws",Info,(word)3,SSparms);
4517         }
4518         break;
4519
4520       case CONF_BEGIN_REQ_PEND:
4521       case CONF_ADD_REQ_PEND:
4522       case CONF_SPLIT_REQ_PEND:
4523       case CONF_DROP_REQ_PEND:
4524       case CONF_ISOLATE_REQ_PEND:
4525       case CONF_REATTACH_REQ_PEND:
4526         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4527         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4528         rplci = plci;
4529         rId = Id;
4530         switch(plci->internal_command)
4531         {
4532           case CONF_BEGIN_REQ_PEND:
4533             SSparms[1] = S_CONF_BEGIN;
4534             break;
4535           case CONF_ADD_REQ_PEND:
4536             SSparms[1] = S_CONF_ADD;
4537             rplci = plci->relatedPTYPLCI;
4538             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4539             break;
4540           case CONF_SPLIT_REQ_PEND:
4541             SSparms[1] = S_CONF_SPLIT;
4542             break;
4543           case CONF_DROP_REQ_PEND:
4544             SSparms[1] = S_CONF_DROP;
4545             break;
4546           case CONF_ISOLATE_REQ_PEND:
4547             SSparms[1] = S_CONF_ISOLATE;
4548             break;
4549           case CONF_REATTACH_REQ_PEND:
4550             SSparms[1] = S_CONF_REATTACH;
4551             break;
4552         }
4553         
4554         if(rc!=OK)
4555         {
4556           Info = 0x300E; /* not supported */
4557           plci->relatedPTYPLCI = NULL;
4558           plci->ptyState = 0;
4559         }
4560         sendf(rplci->appl,
4561               _FACILITY_R|CONFIRM,
4562               rId,
4563               plci->number,
4564               "wws",Info,(word)3,SSparms);
4565         break;
4566
4567       case VSWITCH_REQ_PEND:
4568         if(rc!=OK)
4569         {
4570           if(plci->relatedPTYPLCI)
4571           {
4572             plci->relatedPTYPLCI->vswitchstate=0;
4573             plci->relatedPTYPLCI->vsprot=0;
4574             plci->relatedPTYPLCI->vsprotdialect=0;    
4575           }
4576           plci->vswitchstate=0;
4577           plci->vsprot=0;
4578           plci->vsprotdialect=0;
4579         }
4580         else
4581         {
4582           if(plci->relatedPTYPLCI &&
4583              plci->vswitchstate==1 &&
4584              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4585             plci->vswitchstate=3;
4586         }
4587         break;
4588
4589   /* Call Deflection Request pending (SSCT) */
4590       case CD_REQ_PEND:
4591         SSparms[1] = S_CALL_DEFLECTION;
4592         if(rc!=OK)
4593         {
4594           Info = 0x300E; /* not supported */
4595           plci->appl->CDEnable = 0;
4596         }  
4597         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4598           plci->number,"wws",Info,(word)3,SSparms);
4599         break;
4600
4601       case RTP_CONNECT_B3_REQ_COMMAND_2:
4602         if (rc == OK)
4603         {
4604           ncci = get_ncci (plci, ch, 0);
4605           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4606           plci->channels++;
4607           a->ncci_state[ncci] = OUTG_CON_PENDING;
4608         }
4609
4610       default:
4611         if (plci->internal_command_queue[0])
4612         {
4613           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4614           if (plci->internal_command)
4615             return;
4616         }
4617         break;
4618       }
4619       next_internal_command (Id, plci);
4620     }
4621   }
4622   else /* appl==0 */
4623   {
4624     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4625     if(plci->tel) Id|=EXT_CONTROLLER;
4626
4627     switch(plci->internal_command)
4628     {
4629     case BLOCK_PLCI:
4630       return;
4631
4632     case START_L1_SIG_ASSIGN_PEND:
4633     case REM_L1_SIG_ASSIGN_PEND:
4634       if(global_req == ASSIGN)
4635       {
4636         break;
4637       }
4638       else
4639       {
4640         dbug(1,dprintf("***L1 Req rem PLCI"));
4641         plci->internal_command = 0;
4642         sig_req(plci,REMOVE,0);
4643         send_req(plci);
4644       }
4645       break;
4646
4647       /* Call Deflection Request pending, just no appl ptr assigned */
4648     case CD_REQ_PEND:
4649       SSparms[1] = S_CALL_DEFLECTION;
4650       if(rc!=OK)
4651       {
4652         Info = 0x300E; /* not supported */
4653       }
4654       for(i=0; i<max_appl; i++)
4655       {
4656         if(application[i].CDEnable)
4657         {
4658           if(!application[i].Id) application[i].CDEnable = 0;
4659           else
4660           {
4661             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4662                   plci->number,"wws",Info,(word)3,SSparms);
4663             if(Info) application[i].CDEnable = 0;
4664           }
4665         }
4666       }
4667       plci->internal_command = 0;
4668       break;
4669
4670     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4671       return;
4672
4673     case PERM_COD_CALL:
4674       plci->internal_command = PERM_COD_CONN_PEND;
4675       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4676       return;
4677
4678     case PERM_COD_ASSIGN:
4679       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4680       plci->internal_command = 0;
4681       if(rc!=ASSIGN_OK) break;
4682       plci->internal_command = PERM_COD_CALL;
4683       sig_req(plci,CALL_REQ,0);
4684       send_req(plci);
4685       return;
4686
4687     case LISTEN_SIG_ASSIGN_PEND:
4688       if(rc == ASSIGN_OK)
4689       {
4690         plci->internal_command = 0;
4691         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4692         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4693         sig_req(plci,INDICATE_REQ,0);
4694         send_req(plci);
4695       }
4696       else
4697       {
4698         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4699         a->listen_active--;
4700         plci_remove(plci);
4701         plci->State = IDLE;
4702       }
4703       break;
4704
4705     case USELAW_REQ:
4706       if(global_req == ASSIGN)
4707       {
4708         if (rc==ASSIGN_OK)
4709       {
4710         sig_req(plci,LAW_REQ,0);
4711         send_req(plci);
4712         dbug(1,dprintf("Auto-Law assigned"));
4713         }
4714         else
4715         {
4716           dbug(1,dprintf("Auto-Law assign failed"));
4717           a->automatic_law = 3;
4718           plci->internal_command = 0;
4719           a->automatic_lawPLCI = NULL;
4720         }
4721         break;
4722       }
4723       else if(req == LAW_REQ && rc==OK)
4724       {
4725         dbug(1,dprintf("Auto-Law initiated"));
4726         a->automatic_law = 2;
4727         plci->internal_command = 0;
4728       }
4729       else
4730       {
4731         dbug(1,dprintf("Auto-Law not supported"));
4732         a->automatic_law = 3;
4733         plci->internal_command = 0;
4734         sig_req(plci,REMOVE,0);
4735         send_req(plci);
4736         a->automatic_lawPLCI = NULL;
4737       }
4738       break;
4739     }
4740     plci_remove_check(plci);
4741   }
4742 }
4743
4744 void data_rc(PLCI   * plci, byte ch)
4745 {
4746   dword Id;
4747   DIVA_CAPI_ADAPTER   * a;
4748   NCCI   *ncci_ptr;
4749   DATA_B3_DESC   *data;
4750   word ncci;
4751
4752   if (plci->appl)
4753   {
4754     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4755     a = plci->adapter;
4756     ncci = a->ch_ncci[ch];
4757     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4758     {
4759       ncci_ptr = &(a->ncci[ncci]);
4760       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4761       if (ncci_ptr->data_pending)
4762       {
4763         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4764         if (!(data->Flags &4) && a->ncci_state[ncci])
4765         {
4766           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4767           if(plci->tel) Id|=EXT_CONTROLLER;
4768           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4769                 "ww",data->Handle,0);
4770         }
4771         (ncci_ptr->data_out)++;
4772         if (ncci_ptr->data_out == MAX_DATA_B3)
4773           ncci_ptr->data_out = 0;
4774         (ncci_ptr->data_pending)--;
4775       }
4776     }
4777   }
4778 }
4779
4780 void data_ack(PLCI   * plci, byte ch)
4781 {
4782   dword Id;
4783   DIVA_CAPI_ADAPTER   * a;
4784   NCCI   *ncci_ptr;
4785   word ncci;
4786
4787   a = plci->adapter;
4788   ncci = a->ch_ncci[ch];
4789   ncci_ptr = &(a->ncci[ncci]);
4790   if (ncci_ptr->data_ack_pending)
4791   {
4792     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4793     {
4794       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4795       if(plci->tel) Id|=EXT_CONTROLLER;
4796       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4797             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4798     }
4799     (ncci_ptr->data_ack_out)++;
4800     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4801       ncci_ptr->data_ack_out = 0;
4802     (ncci_ptr->data_ack_pending)--;
4803   }
4804 }
4805
4806 void sig_ind(PLCI   * plci)
4807 {
4808   dword x_Id;
4809   dword Id;
4810   dword rId;
4811   word Number = 0;
4812   word i;
4813   word cip;
4814   dword cip_mask;
4815   byte   *ie;
4816   DIVA_CAPI_ADAPTER   * a;
4817     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4818 #define MAXPARMSIDS 31
4819     byte   * parms[MAXPARMSIDS];
4820     byte   * add_i[4];
4821     byte   * multi_fac_parms[MAX_MULTI_IE];
4822     byte   * multi_pi_parms [MAX_MULTI_IE];
4823     byte   * multi_ssext_parms [MAX_MULTI_IE];
4824     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4825
4826     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4827
4828   byte ai_len;
4829     byte   *esc_chi = "";
4830     byte   *esc_law = "";
4831     byte   *pty_cai = "";
4832     byte   *esc_cr  = "";
4833     byte   *esc_profile = "";
4834
4835     byte facility[256];
4836   PLCI   * tplci = NULL;
4837   byte chi[] = "\x02\x18\x01";
4838   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4839     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4840   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4841   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4842   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4843   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4844     word parms_id[] =
4845          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4846           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4847           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4848           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4849           /* 14 FTY repl by ESC_CHI */
4850           /* 18 PI  repl by ESC_LAW */
4851          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4852      word multi_fac_id[] = {1, FTY};
4853      word multi_pi_id[]  = {1, PI};
4854      word multi_CiPN_id[]  = {1, OAD};
4855      word multi_ssext_id[]  = {1, ESC_SSEXT};
4856
4857      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4858
4859   byte   * cau;
4860   word ncci;
4861     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4862     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4863     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4864     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4865   byte force_mt_info = FALSE;
4866   byte dir;
4867   dword d;
4868   word w;
4869
4870   a = plci->adapter;
4871   Id = ((word)plci->Id<<8)|a->Id;
4872   PUT_WORD(&SS_Ind[4],0x0000);
4873
4874   if (plci->sig_remove_id)
4875   {
4876     plci->Sig.RNR = 2; /* discard */
4877     dbug(1,dprintf("SIG discard while remove pending"));
4878     return;
4879   }
4880   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4881   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4882     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4883   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4884   {
4885     plci->Sig.RNR = 1;
4886     return;
4887   }
4888   if(plci->Sig.Ind==HANGUP && plci->channels)
4889   {
4890     plci->Sig.RNR = 1;
4891     plci->hangup_flow_ctrl_timer++;
4892     /* recover the network layer after timeout */
4893     if(plci->hangup_flow_ctrl_timer==100)
4894     {
4895       dbug(1,dprintf("Exceptional disc"));
4896       plci->Sig.RNR = 0;
4897       plci->hangup_flow_ctrl_timer = 0;
4898       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4899       {
4900         if (a->ncci_plci[ncci] == plci->Id)
4901         {
4902           cleanup_ncci_data (plci, ncci);
4903           if(plci->channels)plci->channels--;
4904           if (plci->appl)
4905             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4906         }
4907       }
4908       if (plci->appl)
4909         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4910       plci_remove(plci);
4911       plci->State=IDLE;
4912     }
4913     return;
4914   }
4915
4916   /* do first parse the info with no OAD in, because OAD will be converted */
4917   /* first the multiple facility IE, then mult. progress ind.              */
4918   /* then the parameters for the info_ind + conn_ind                       */
4919   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4920   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4921   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4922
4923   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4924
4925   IndParse(plci,parms_id,parms,0);
4926   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4927   esc_chi  = parms[14];
4928   esc_law  = parms[18];
4929   pty_cai  = parms[24];
4930   esc_cr   = parms[25];
4931   esc_profile = parms[27];
4932   if(esc_cr[0] && plci)
4933   {
4934     if(plci->cr_enquiry && plci->appl)
4935     {
4936       plci->cr_enquiry = FALSE;
4937       /* d = MANU_ID            */
4938       /* w = m_command          */
4939       /* b = total length       */
4940       /* b = indication type    */
4941       /* b = length of all IEs  */
4942       /* b = IE1                */
4943       /* S = IE1 length + cont. */
4944       /* b = IE2                */
4945       /* S = IE2 lenght + cont. */
4946       sendf(plci->appl,
4947         _MANUFACTURER_I,
4948         Id,
4949         0,
4950         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4951         2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law);
4952     }
4953   }
4954   /* create the additional info structure                                  */
4955   add_i[1] = parms[15]; /* KEY of additional info */
4956   add_i[2] = parms[11]; /* UUI of additional info */
4957   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4958
4959   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4960   /* indication returns by the card if requested by the function           */
4961   /* AutomaticLaw() after driver init                                      */
4962   if (a->automatic_law<4)
4963   {
4964     if(esc_law[0]){
4965       if(esc_law[2]){
4966         dbug(0,dprintf("u-Law selected"));
4967         a->u_law = 1;
4968       }
4969       else {
4970         dbug(0,dprintf("a-Law selected"));
4971         a->u_law = 0;
4972       }
4973       a->automatic_law = 4;
4974       if(plci==a->automatic_lawPLCI) {
4975         plci->internal_command = 0;
4976         sig_req(plci,REMOVE,0);
4977         send_req(plci);
4978         a->automatic_lawPLCI = NULL;
4979       }
4980     }
4981     if (esc_profile[0])
4982     {
4983       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4984         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4985         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4986         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4987
4988       a->profile.Global_Options &= 0x000000ffL;
4989       a->profile.B1_Protocols &= 0x000003ffL;
4990       a->profile.B2_Protocols &= 0x00001fdfL;
4991       a->profile.B3_Protocols &= 0x000000b7L;
4992
4993       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4994         GL_BCHANNEL_OPERATION_SUPPORTED;
4995       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4996       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4997       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4998       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4999       a->man_profile.private_options = 0;
5000
5001       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5002       {
5003         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5004         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5005       }
5006
5007
5008       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5009         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5010       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5011       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5012
5013
5014       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5015         a->man_profile.private_options |= 1L << PRIVATE_T38;
5016
5017
5018       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5019         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5020
5021
5022       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5023         a->man_profile.private_options |= 1L << PRIVATE_V18;
5024
5025
5026       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5027         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5028
5029
5030       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5031         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5032
5033
5034       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5035         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5036
5037
5038       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5039         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5040
5041
5042       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5043         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5044
5045     }
5046     else
5047     {
5048       a->profile.Global_Options &= 0x0000007fL;
5049       a->profile.B1_Protocols &= 0x000003dfL;
5050       a->profile.B2_Protocols &= 0x00001adfL;
5051       a->profile.B3_Protocols &= 0x000000b7L;
5052       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5053     }
5054     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5055       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5056     {
5057       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5058     }
5059     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5060     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5061       UnMapController (a->Id), a->profile.Global_Options,
5062       a->profile.B1_Protocols, a->profile.B2_Protocols,
5063       a->profile.B3_Protocols, a->manufacturer_features));
5064   }
5065   /* codec plci for the handset/hook state support is just an internal id  */
5066   if(plci!=a->AdvCodecPLCI)
5067   {
5068     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5069     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5070     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5071     SendInfo(plci,Id, parms, force_mt_info);
5072
5073     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5074
5075   }
5076
5077   /* switch the codec to the b-channel                                     */
5078   if(esc_chi[0] && plci && !plci->SuppState){
5079     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5080     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5081     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5082     if(plci->tel==ADV_VOICE && plci->appl) {
5083       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5084     }
5085   }
5086
5087   if(plci->appl) Number = plci->appl->Number++;
5088
5089   switch(plci->Sig.Ind) {
5090   /* Response to Get_Supported_Services request */
5091   case S_SUPPORTED:
5092     dbug(1,dprintf("S_Supported"));
5093     if(!plci->appl) break;
5094     if(pty_cai[0]==4)
5095     {
5096       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5097     }
5098     else
5099     {
5100       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5101     }
5102     PUT_WORD (&CF_Ind[1], 0);
5103     PUT_WORD (&CF_Ind[4], 0);
5104     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5105     plci_remove(plci);
5106     break;
5107                     
5108   /* Supplementary Service rejected */
5109   case S_SERVICE_REJ:
5110     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5111     if(!pty_cai[0]) break;
5112     switch (pty_cai[5])
5113     {
5114     case ECT_EXECUTE:
5115     case THREE_PTY_END:
5116     case THREE_PTY_BEGIN:
5117       if(!plci->relatedPTYPLCI) break;
5118       tplci = plci->relatedPTYPLCI;
5119       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5120       if(tplci->tel) rId|=EXT_CONTROLLER;
5121       if(pty_cai[5]==ECT_EXECUTE)
5122       {
5123         PUT_WORD(&SS_Ind[1],S_ECT);
5124
5125         plci->vswitchstate=0;
5126         plci->relatedPTYPLCI->vswitchstate=0;
5127
5128       }
5129       else
5130       {
5131         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5132       }
5133       if(pty_cai[2]!=0xff)
5134       {
5135         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5136       }
5137       else
5138       {
5139         PUT_WORD(&SS_Ind[4],0x300E);
5140       }
5141       plci->relatedPTYPLCI = NULL;
5142       plci->ptyState = 0;
5143       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5144       break;
5145
5146     case CALL_DEFLECTION:
5147       if(pty_cai[2]!=0xff)
5148       {
5149         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5150       }
5151       else
5152       {
5153         PUT_WORD(&SS_Ind[4],0x300E);
5154       }
5155       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5156       for(i=0; i<max_appl; i++)
5157       {
5158         if(application[i].CDEnable)
5159         {
5160           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5161           application[i].CDEnable = FALSE;
5162         }
5163       }
5164       break;
5165
5166     case DEACTIVATION_DIVERSION:
5167     case ACTIVATION_DIVERSION:
5168     case DIVERSION_INTERROGATE_CFU:
5169     case DIVERSION_INTERROGATE_CFB:
5170     case DIVERSION_INTERROGATE_CFNR:
5171     case DIVERSION_INTERROGATE_NUM:
5172     case CCBS_REQUEST:
5173     case CCBS_DEACTIVATE:
5174     case CCBS_INTERROGATE:
5175       if(!plci->appl) break;
5176       if(pty_cai[2]!=0xff)
5177       {
5178         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5179       }
5180       else
5181       {
5182         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5183       }
5184       switch (pty_cai[5])
5185       {
5186         case DEACTIVATION_DIVERSION:
5187           dbug(1,dprintf("Deact_Div"));
5188           Interr_Err_Ind[0]=0x9;
5189           Interr_Err_Ind[3]=0x6;
5190           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5191           break;
5192         case ACTIVATION_DIVERSION:
5193           dbug(1,dprintf("Act_Div"));
5194           Interr_Err_Ind[0]=0x9;
5195           Interr_Err_Ind[3]=0x6;
5196           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5197           break;
5198         case DIVERSION_INTERROGATE_CFU:
5199         case DIVERSION_INTERROGATE_CFB:
5200         case DIVERSION_INTERROGATE_CFNR:
5201           dbug(1,dprintf("Interr_Div"));
5202           Interr_Err_Ind[0]=0xa;
5203           Interr_Err_Ind[3]=0x7;
5204           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5205           break;
5206         case DIVERSION_INTERROGATE_NUM:
5207           dbug(1,dprintf("Interr_Num"));
5208           Interr_Err_Ind[0]=0xa;
5209           Interr_Err_Ind[3]=0x7;
5210           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5211           break;
5212         case CCBS_REQUEST:
5213           dbug(1,dprintf("CCBS Request"));
5214           Interr_Err_Ind[0]=0xd;
5215           Interr_Err_Ind[3]=0xa;
5216           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5217           break;
5218         case CCBS_DEACTIVATE:
5219           dbug(1,dprintf("CCBS Deactivate"));
5220           Interr_Err_Ind[0]=0x9;
5221           Interr_Err_Ind[3]=0x6;
5222           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5223           break;
5224         case CCBS_INTERROGATE:
5225           dbug(1,dprintf("CCBS Interrogate"));
5226           Interr_Err_Ind[0]=0xb;
5227           Interr_Err_Ind[3]=0x8;
5228           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5229           break;
5230       }
5231       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5232       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5233       plci_remove(plci);
5234       break;
5235     case ACTIVATION_MWI:      
5236     case DEACTIVATION_MWI:
5237       if(pty_cai[5]==ACTIVATION_MWI)
5238       {
5239         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5240       }
5241       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5242       
5243       if(pty_cai[2]!=0xff)
5244       {
5245         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5246       }
5247       else
5248       {
5249         PUT_WORD(&SS_Ind[4],0x300E);
5250       }
5251
5252       if(plci->cr_enquiry)
5253       {
5254         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5255         plci_remove(plci);
5256       }
5257       else
5258       {
5259         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5260       }
5261       break;
5262     case CONF_ADD: /* ERROR */
5263     case CONF_BEGIN:
5264     case CONF_DROP:
5265     case CONF_ISOLATE:
5266     case CONF_REATTACH:
5267       CONF_Ind[0]=9;
5268       CONF_Ind[3]=6;   
5269       switch(pty_cai[5])
5270       {
5271       case CONF_BEGIN:
5272           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5273           plci->ptyState = 0;
5274           break;
5275       case CONF_DROP:
5276           CONF_Ind[0]=5;
5277           CONF_Ind[3]=2;
5278           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5279           plci->ptyState = CONNECTED;
5280           break;
5281       case CONF_ISOLATE:
5282           CONF_Ind[0]=5;
5283           CONF_Ind[3]=2;
5284           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5285           plci->ptyState = CONNECTED;
5286           break;
5287       case CONF_REATTACH:
5288           CONF_Ind[0]=5;
5289           CONF_Ind[3]=2;
5290           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5291           plci->ptyState = CONNECTED;
5292           break;
5293       case CONF_ADD:
5294           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5295           plci->relatedPTYPLCI = NULL;
5296           tplci=plci->relatedPTYPLCI;
5297           if(tplci) tplci->ptyState = CONNECTED;
5298           plci->ptyState = CONNECTED;
5299           break;
5300       }
5301           
5302       if(pty_cai[2]!=0xff)
5303       {
5304         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5305       }
5306       else
5307       {
5308         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5309                                             within the required time */
5310       }
5311
5312       PUT_DWORD(&CONF_Ind[6],0x0);
5313       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5314       break;
5315     }
5316     break;
5317
5318   /* Supplementary Service indicates success */
5319   case S_SERVICE:
5320     dbug(1,dprintf("Service_Ind"));
5321     PUT_WORD (&CF_Ind[4], 0);
5322     switch (pty_cai[5])
5323     {
5324     case THREE_PTY_END:
5325     case THREE_PTY_BEGIN:
5326     case ECT_EXECUTE:
5327       if(!plci->relatedPTYPLCI) break;
5328       tplci = plci->relatedPTYPLCI;
5329       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5330       if(tplci->tel) rId|=EXT_CONTROLLER;
5331       if(pty_cai[5]==ECT_EXECUTE)
5332       {
5333         PUT_WORD(&SS_Ind[1],S_ECT);
5334
5335         if(plci->vswitchstate!=3)
5336         {
5337
5338         plci->ptyState = IDLE;
5339         plci->relatedPTYPLCI = NULL;
5340         plci->ptyState = 0;
5341
5342         }
5343
5344         dbug(1,dprintf("ECT OK"));
5345         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5346
5347
5348
5349       }
5350       else
5351       {
5352         switch (plci->ptyState)
5353         {
5354         case S_3PTY_BEGIN:
5355           plci->ptyState = CONNECTED;
5356           dbug(1,dprintf("3PTY ON"));
5357           break;
5358
5359         case S_3PTY_END:
5360           plci->ptyState = IDLE;
5361           plci->relatedPTYPLCI = NULL;
5362           plci->ptyState = 0;
5363           dbug(1,dprintf("3PTY OFF"));
5364           break;
5365         }
5366         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5367         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5368       }
5369       break;
5370
5371     case CALL_DEFLECTION:
5372       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5373       for(i=0; i<max_appl; i++)
5374       {
5375         if(application[i].CDEnable)
5376         {
5377           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5378           application[i].CDEnable = FALSE;
5379         }
5380       }
5381       break;
5382
5383     case DEACTIVATION_DIVERSION:
5384     case ACTIVATION_DIVERSION:
5385       if(!plci->appl) break;
5386       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5387       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5388       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5389       plci_remove(plci);
5390       break;
5391
5392     case DIVERSION_INTERROGATE_CFU:
5393     case DIVERSION_INTERROGATE_CFB:
5394     case DIVERSION_INTERROGATE_CFNR:
5395     case DIVERSION_INTERROGATE_NUM:
5396     case CCBS_REQUEST:
5397     case CCBS_DEACTIVATE:
5398     case CCBS_INTERROGATE:
5399       if(!plci->appl) break;
5400       switch (pty_cai[5])
5401       {
5402         case DIVERSION_INTERROGATE_CFU:
5403         case DIVERSION_INTERROGATE_CFB:
5404         case DIVERSION_INTERROGATE_CFNR:
5405           dbug(1,dprintf("Interr_Div"));
5406           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5407           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5408           break;
5409         case DIVERSION_INTERROGATE_NUM:
5410           dbug(1,dprintf("Interr_Num"));
5411           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5412           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5413           break;
5414         case CCBS_REQUEST:
5415           dbug(1,dprintf("CCBS Request"));
5416           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5417           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5418           break;
5419         case CCBS_DEACTIVATE:
5420           dbug(1,dprintf("CCBS Deactivate"));
5421           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5422           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5423           break;
5424         case CCBS_INTERROGATE:
5425           dbug(1,dprintf("CCBS Interrogate"));
5426           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5427           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5428           break;
5429       }
5430       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5431       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5432       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5433       plci_remove(plci);
5434       break;
5435
5436     case ACTIVATION_MWI:
5437     case DEACTIVATION_MWI:
5438       if(pty_cai[5]==ACTIVATION_MWI)
5439       {
5440         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5441       }
5442       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5443       if(plci->cr_enquiry)
5444       {
5445         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5446         plci_remove(plci);
5447       }
5448       else
5449       {
5450         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5451       }
5452       break;
5453     case MWI_INDICATION:
5454       if(pty_cai[0]>=0x12)
5455       {
5456         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5457         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5458         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5459         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5460         {
5461           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5462           {
5463             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5464             plci_remove(plci);
5465             return;
5466           }
5467           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5468           pty_cai[0]=0;
5469         }
5470         else
5471         {
5472           for(i=0; i<max_appl; i++)
5473           {                     
5474             if(a->Notification_Mask[i]&SMASK_MWI)
5475             {
5476               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5477               pty_cai[0]=0;
5478             }
5479           }
5480         }
5481
5482         if(!pty_cai[0])
5483         { /* acknowledge */
5484           facility[2]= 0; /* returncode */
5485         }
5486         else facility[2]= 0xff;
5487       }
5488       else
5489       {
5490         /* reject */
5491         facility[2]= 0xff; /* returncode */
5492       }
5493       facility[0]= 2;
5494       facility[1]= MWI_RESPONSE; /* Function */
5495       add_p(plci,CAI,facility);
5496       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5497       sig_req(plci,S_SERVICE,0);
5498       send_req(plci);
5499       plci->command = 0;
5500       next_internal_command (Id, plci);
5501       break;
5502     case CONF_ADD: /* OK */
5503     case CONF_BEGIN:
5504     case CONF_DROP:
5505     case CONF_ISOLATE:
5506     case CONF_REATTACH:
5507     case CONF_PARTYDISC:
5508       CONF_Ind[0]=9;
5509       CONF_Ind[3]=6;
5510       switch(pty_cai[5])
5511       {
5512       case CONF_BEGIN:
5513           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5514           if(pty_cai[0]==6)
5515           {
5516               d=pty_cai[6];
5517               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5518           }
5519           else
5520           {
5521               PUT_DWORD(&CONF_Ind[6],0x0);
5522           }
5523           break;
5524       case CONF_ISOLATE:
5525           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5526           CONF_Ind[0]=5;
5527           CONF_Ind[3]=2;
5528           break;
5529       case CONF_REATTACH:
5530           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5531           CONF_Ind[0]=5;
5532           CONF_Ind[3]=2;
5533           break;
5534       case CONF_DROP:
5535           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5536           CONF_Ind[0]=5;
5537           CONF_Ind[3]=2;
5538           break;
5539       case CONF_ADD:
5540           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5541           d=pty_cai[6];
5542           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5543           tplci=plci->relatedPTYPLCI;
5544           if(tplci) tplci->ptyState = CONNECTED;
5545           break;
5546       case CONF_PARTYDISC:
5547           CONF_Ind[0]=7;
5548           CONF_Ind[3]=4;          
5549           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5550           d=pty_cai[6];
5551           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5552           break;
5553       }
5554       plci->ptyState = CONNECTED;
5555       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5556       break;
5557     case CCBS_INFO_RETAIN:
5558     case CCBS_ERASECALLLINKAGEID:
5559     case CCBS_STOP_ALERTING:
5560       CONF_Ind[0]=5;
5561       CONF_Ind[3]=2;
5562       switch(pty_cai[5])
5563       {
5564       case CCBS_INFO_RETAIN:
5565         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5566         break;
5567       case CCBS_STOP_ALERTING:
5568         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5569     break;
5570       case CCBS_ERASECALLLINKAGEID:
5571         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5572         CONF_Ind[0]=7;
5573         CONF_Ind[3]=4;
5574         CONF_Ind[6]=0;
5575         CONF_Ind[7]=0;
5576         break;
5577       }      
5578       w=pty_cai[6];
5579       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5580
5581       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5582       {
5583         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5584       }
5585       else
5586       {
5587         for(i=0; i<max_appl; i++)
5588             if(a->Notification_Mask[i]&SMASK_CCBS)
5589                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5590       }
5591       break;
5592     }
5593     break;
5594   case CALL_HOLD_REJ:
5595     cau = parms[7];
5596     if(cau)
5597     {
5598       i = _L3_CAUSE | cau[2];
5599       if(cau[2]==0) i = 0x3603;
5600     }
5601     else
5602     {
5603       i = 0x3603;
5604     }
5605     PUT_WORD(&SS_Ind[1],S_HOLD);
5606     PUT_WORD(&SS_Ind[4],i);
5607     if(plci->SuppState == HOLD_REQUEST)
5608     {
5609       plci->SuppState = IDLE;
5610       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5611     }
5612     break;
5613
5614   case CALL_HOLD_ACK:
5615     if(plci->SuppState == HOLD_REQUEST)
5616     {
5617       plci->SuppState = CALL_HELD;
5618       CodecIdCheck(a, plci);
5619       start_internal_command (Id, plci, hold_save_command);
5620     }
5621     break;
5622
5623   case CALL_RETRIEVE_REJ:
5624     cau = parms[7];
5625     if(cau)
5626     {
5627       i = _L3_CAUSE | cau[2];
5628       if(cau[2]==0) i = 0x3603;
5629     }
5630     else
5631     {
5632       i = 0x3603;
5633     }
5634     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5635     PUT_WORD(&SS_Ind[4],i);
5636     if(plci->SuppState == RETRIEVE_REQUEST)
5637     {
5638       plci->SuppState = CALL_HELD;
5639       CodecIdCheck(a, plci);
5640       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5641     }
5642     break;
5643
5644   case CALL_RETRIEVE_ACK:
5645     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5646     if(plci->SuppState == RETRIEVE_REQUEST)
5647     {
5648       plci->SuppState = IDLE;
5649       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5650       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5651       if(plci->tel)
5652       {
5653         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5654         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5655         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5656         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5657         {
5658           dbug(1,dprintf("Get B-ch"));
5659           start_internal_command (Id, plci, retrieve_restore_command);
5660         }
5661         else
5662           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5663       }
5664       else
5665         start_internal_command (Id, plci, retrieve_restore_command);
5666     }
5667     break;
5668
5669   case INDICATE_IND:
5670     if(plci->State != LISTENING) {
5671       sig_req(plci,HANGUP,0);
5672       send_req(plci);
5673       break;
5674     }
5675     cip = find_cip(a,parms[4],parms[6]);
5676     cip_mask = 1L<<cip;
5677     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5678     clear_c_ind_mask (plci);
5679     if (!remove_started && !a->adapter_disabled)
5680     {
5681       set_c_ind_mask_bit (plci, MAX_APPL);
5682       group_optimization(a, plci);
5683       for(i=0; i<max_appl; i++) {
5684         if(application[i].Id
5685         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5686         && CPN_filter_ok(parms[0],a,i)
5687         && test_group_ind_mask_bit (plci, i) ) {
5688           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5689           set_c_ind_mask_bit (plci, i);
5690           dump_c_ind_mask (plci);
5691           plci->State = INC_CON_PENDING;
5692           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5693             CALL_DIR_IN | CALL_DIR_ANSWER;
5694           if(esc_chi[0]) {
5695             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5696             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5697           }
5698           /* if a listen on the ext controller is done, check if hook states */
5699           /* are supported or if just a on board codec must be activated     */
5700           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5701             if(a->profile.Global_Options & HANDSET)
5702               plci->tel = ADV_VOICE;
5703             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5704               plci->tel = CODEC;
5705             if(plci->tel) Id|=EXT_CONTROLLER;
5706             a->codec_listen[i] = plci;
5707           }
5708
5709           sendf(&application[i],_CONNECT_I,Id,0,
5710                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5711                              parms[0],    /* CalledPartyNumber   */
5712                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5713                              parms[2],    /* CalledPartySubad    */
5714                              parms[3],    /* CallingPartySubad   */
5715                              parms[4],    /* BearerCapability    */
5716                              parms[5],    /* LowLC               */
5717                              parms[6],    /* HighLC              */
5718                              ai_len,      /* nested struct add_i */
5719                              add_i[0],    /* B channel info    */
5720                              add_i[1],    /* keypad facility   */
5721                              add_i[2],    /* user user data    */
5722                              add_i[3],    /* nested facility   */
5723                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5724                              );
5725           SendSSExtInd(&application[i],
5726                         plci,
5727                         Id,
5728                         multi_ssext_parms);
5729           SendSetupInfo(&application[i],
5730                         plci,
5731                         Id,
5732                         parms,
5733                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE));
5734         }
5735       }
5736       clear_c_ind_mask_bit (plci, MAX_APPL);
5737       dump_c_ind_mask (plci);
5738     }
5739     if(c_ind_mask_empty (plci)) {
5740       sig_req(plci,HANGUP,0);
5741       send_req(plci);
5742       plci->State = IDLE;
5743     }
5744     plci->notifiedcall = 0;
5745     a->listen_active--;
5746     listen_check(a);
5747     break;
5748
5749   case CALL_PEND_NOTIFY:
5750     plci->notifiedcall = 1;
5751     listen_check(a);
5752     break;
5753
5754   case CALL_IND:
5755   case CALL_CON:
5756     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5757     {
5758       if(plci->internal_command==PERM_COD_CONN_PEND)
5759       {
5760         if(plci->State==ADVANCED_VOICE_NOSIG)
5761         {
5762           dbug(1,dprintf("***Codec OK"));
5763           if(a->AdvSignalPLCI)
5764           {
5765             tplci = a->AdvSignalPLCI;
5766             if(tplci->spoofed_msg)
5767             {
5768               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5769               tplci->command = 0;
5770               tplci->internal_command = 0;
5771               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5772               switch (tplci->spoofed_msg)
5773               {
5774               case CALL_RES:
5775                 tplci->command = _CONNECT_I|RESPONSE;
5776                 api_load_msg (&tplci->saved_msg, saved_parms);
5777                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5778                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5779                 {
5780                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5781                   add_p(tplci,LLI,"\x01\x01");
5782                 }
5783                 add_s(tplci, CONN_NR, &saved_parms[2]);
5784                 add_s(tplci, LLC, &saved_parms[4]);
5785                 add_ai(tplci, &saved_parms[5]);
5786                 tplci->State = INC_CON_ACCEPT;
5787                 sig_req(tplci, CALL_RES,0);
5788                 send_req(tplci);
5789                 break;
5790
5791               case AWAITING_SELECT_B:
5792                 dbug(1,dprintf("Select_B continue"));
5793                 start_internal_command (x_Id, tplci, select_b_command);
5794                 break;
5795
5796               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5797                 if(!tplci->Sig.Id)
5798                 {
5799                   dbug(1,dprintf("No SigID!"));
5800                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5801                   plci_remove(tplci);
5802                   break;
5803                 }
5804                 tplci->command = _MANUFACTURER_R;
5805                 api_load_msg (&tplci->saved_msg, saved_parms);
5806                 dir = saved_parms[2].info[0];
5807                 if(dir==1) {
5808                   sig_req(tplci,CALL_REQ,0);
5809                 }
5810                 else if(!dir){
5811                   sig_req(tplci,LISTEN_REQ,0);
5812                 }
5813                 send_req(tplci);
5814                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5815                 break;
5816
5817               case (CALL_REQ|AWAITING_MANUF_CON):
5818                 sig_req(tplci,CALL_REQ,0);
5819                 send_req(tplci);
5820                 break;
5821
5822               case CALL_REQ:
5823                 if(!tplci->Sig.Id)
5824                 {
5825                   dbug(1,dprintf("No SigID!"));
5826                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5827                   plci_remove(tplci);
5828                   break;
5829                 }
5830                 tplci->command = _CONNECT_R;
5831                 api_load_msg (&tplci->saved_msg, saved_parms);
5832                 add_s(tplci,CPN,&saved_parms[1]);
5833                 add_s(tplci,DSA,&saved_parms[3]);
5834                 add_ai(tplci,&saved_parms[9]);
5835                 sig_req(tplci,CALL_REQ,0);
5836                 send_req(tplci);
5837                 break;
5838
5839               case CALL_RETRIEVE:
5840                 tplci->command = C_RETRIEVE_REQ;
5841                 sig_req(tplci,CALL_RETRIEVE,0);
5842                 send_req(tplci);
5843                 break;
5844               }
5845               tplci->spoofed_msg = 0;
5846               if (tplci->internal_command == 0)
5847                 next_internal_command (x_Id, tplci);
5848             }
5849           }
5850           next_internal_command (Id, plci);
5851           break;
5852         }
5853         dbug(1,dprintf("***Codec Hook Init Req"));
5854         plci->internal_command = PERM_COD_HOOK;
5855         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5856         sig_req(plci,TEL_CTRL,0);
5857         send_req(plci);
5858       }
5859     }
5860     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5861     && plci->State!=INC_ACT_PENDING)
5862     {
5863       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5864       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5865       {
5866         chi[2] = plci->b_channel;
5867         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5868       }
5869       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5870       plci->State = INC_ACT_PENDING;
5871     }
5872     break;
5873
5874   case TEL_CTRL:
5875     Number = 0;
5876     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5877     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5878       switch (ie[1]&0x91) {
5879         case 0x80:   /* hook off */
5880         case 0x81:
5881           if(plci->internal_command==PERM_COD_HOOK)
5882           {
5883             dbug(1,dprintf("init:hook_off"));
5884             plci->hook_state = ie[1];
5885             next_internal_command (Id, plci);
5886             break;
5887           }
5888           else /* ignore doubled hook indications */
5889           {
5890             if( ((plci->hook_state)&0xf0)==0x80)
5891             {
5892               dbug(1,dprintf("ignore hook"));
5893               break;
5894             }
5895             plci->hook_state = ie[1]&0x91;
5896           }
5897           /* check for incoming call pending */
5898           /* and signal '+'.Appl must decide */
5899           /* with connect_res if call must   */
5900           /* accepted or not                 */
5901           for(i=0, tplci=NULL;i<max_appl;i++){
5902             if(a->codec_listen[i]
5903             && (a->codec_listen[i]->State==INC_CON_PENDING
5904               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5905               tplci = a->codec_listen[i];
5906               tplci->appl = &application[i];
5907             }
5908           }
5909           /* no incoming call, do outgoing call */
5910           /* and signal '+' if outg. setup   */
5911           if(!a->AdvSignalPLCI && !tplci){
5912             if((i=get_plci(a))) {
5913               a->AdvSignalPLCI = &a->plci[i-1];
5914               tplci = a->AdvSignalPLCI;
5915               tplci->tel  = ADV_VOICE;
5916               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5917               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5918                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5919                 add_p(tplci,LLI,"\x01\x01");
5920               }
5921               add_p(tplci, CAI, voice_cai);
5922               add_p(tplci, OAD, a->TelOAD);
5923               add_p(tplci, OSA, a->TelOSA);
5924               add_p(tplci,SHIFT|6,NULL);
5925               add_p(tplci,SIN,"\x02\x01\x00");
5926               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5927               sig_req(tplci,ASSIGN,DSIG_ID);
5928               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5929               a->AdvSignalPLCI->command = 0;
5930               tplci->appl = a->AdvSignalAppl;
5931               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5932               send_req(tplci);
5933             }
5934
5935           }
5936
5937           if(!tplci) break;
5938           Id = ((word)tplci->Id<<8)|a->Id;
5939           Id|=EXT_CONTROLLER;
5940           sendf(tplci->appl,
5941                 _FACILITY_I,
5942                 Id,
5943                 0,
5944                 "ws", (word)0, "\x01+");
5945           break;
5946
5947         case 0x90:   /* hook on  */
5948         case 0x91:
5949           if(plci->internal_command==PERM_COD_HOOK)
5950           {
5951             dbug(1,dprintf("init:hook_on"));
5952             plci->hook_state = ie[1]&0x91;
5953             next_internal_command (Id, plci);
5954             break;
5955           }
5956           else /* ignore doubled hook indications */
5957           {
5958             if( ((plci->hook_state)&0xf0)==0x90) break;
5959             plci->hook_state = ie[1]&0x91;
5960           }
5961           /* hangup the adv. voice call and signal '-' to the appl */
5962           if(a->AdvSignalPLCI) {
5963             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5964             if(plci->tel) Id|=EXT_CONTROLLER;
5965             sendf(a->AdvSignalAppl,
5966                   _FACILITY_I,
5967                   Id,
5968                   0,
5969                   "ws", (word)0, "\x01-");
5970             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5971             a->AdvSignalPLCI->command = 0;
5972             sig_req(a->AdvSignalPLCI,HANGUP,0);
5973             send_req(a->AdvSignalPLCI);
5974           }
5975           break;
5976       }
5977     }
5978     break;
5979
5980   case RESUME:
5981     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5982     PUT_WORD(&resume_cau[4],GOOD);
5983     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5984     break;
5985
5986   case SUSPEND:
5987     clear_c_ind_mask (plci);
5988
5989     if (plci->NL.Id && !plci->nl_remove_id) {
5990       mixer_remove (plci);
5991       nl_req_ncci(plci,REMOVE,0);
5992     }
5993     if (!plci->sig_remove_id) {
5994       plci->internal_command = 0;
5995       sig_req(plci,REMOVE,0);
5996     }
5997     send_req(plci);
5998     if(!plci->channels) {
5999       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6000       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6001     }
6002     break;
6003
6004   case SUSPEND_REJ:
6005     break;
6006
6007   case HANGUP:
6008     plci->hangup_flow_ctrl_timer=0;
6009     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6010     cau = parms[7];
6011     if(cau) {
6012       i = _L3_CAUSE | cau[2];
6013       if(cau[2]==0) i = 0;
6014       else if(cau[2]==8) i = _L1_ERROR;
6015       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6016       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6017     }
6018     else {
6019       i = _L3_ERROR;
6020     }
6021
6022     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6023     {
6024       for(i=0; i<max_appl; i++)
6025       {
6026         if(test_c_ind_mask_bit (plci, i))
6027           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6028       }
6029     }
6030     else
6031     {
6032       clear_c_ind_mask (plci);
6033     }
6034     if(!plci->appl)
6035     {
6036       if (plci->State == LISTENING)
6037       {
6038         plci->notifiedcall=0;
6039         a->listen_active--;
6040       }
6041       plci->State = INC_DIS_PENDING;
6042       if(c_ind_mask_empty (plci))
6043       {
6044         plci->State = IDLE;
6045         if (plci->NL.Id && !plci->nl_remove_id)
6046         {
6047           mixer_remove (plci);
6048           nl_req_ncci(plci,REMOVE,0);
6049         }
6050         if (!plci->sig_remove_id)
6051         {
6052           plci->internal_command = 0;
6053           sig_req(plci,REMOVE,0);
6054         }
6055         send_req(plci);
6056       }
6057     }
6058     else
6059     {
6060         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6061         /* result in a second HANGUP! Don't generate another        */
6062         /* DISCONNECT                                               */
6063       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6064       {
6065         if(plci->State==RESUMING)
6066         {
6067           PUT_WORD(&resume_cau[4],i);
6068           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6069         }
6070         plci->State = INC_DIS_PENDING;
6071         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6072       }
6073     }
6074     break;
6075
6076   case SSEXT_IND:
6077     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6078     break;
6079
6080   case VSWITCH_REQ:
6081     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6082     break;
6083   case VSWITCH_IND:
6084  if(plci->relatedPTYPLCI &&
6085   plci->vswitchstate==3 &&
6086   plci->relatedPTYPLCI->vswitchstate==3 &&
6087   parms[MAXPARMSIDS-1][0])
6088  {
6089   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6090   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6091   send_req(plci->relatedPTYPLCI);
6092  }
6093     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6094     break;
6095
6096   }
6097 }
6098
6099
6100 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6101 {
6102   word i;
6103   byte   * ie;
6104   word Info_Number;
6105   byte   * Info_Element;
6106   word Info_Mask = 0;
6107
6108   dbug(1,dprintf("SetupInfo"));
6109
6110   for(i=0; i<MAXPARMSIDS; i++) {
6111     ie = parms[i];
6112     Info_Number = 0;
6113     Info_Element = ie;
6114     if(ie[0]) {
6115       switch(i) {
6116       case 0:
6117         dbug(1,dprintf("CPN "));
6118         Info_Number = 0x0070;
6119         Info_Mask   = 0x80;
6120         Info_Sent_Flag = TRUE;
6121         break;
6122       case 8:  /* display      */
6123         dbug(1,dprintf("display(%d)",i));
6124         Info_Number = 0x0028;
6125         Info_Mask = 0x04;
6126         Info_Sent_Flag = TRUE;
6127         break;
6128       case 16: /* Channel Id */
6129         dbug(1,dprintf("CHI"));
6130         Info_Number = 0x0018;
6131         Info_Mask = 0x100;
6132         Info_Sent_Flag = TRUE;
6133         mixer_set_bchannel_id (plci, Info_Element);
6134         break;
6135       case 19: /* Redirected Number */
6136         dbug(1,dprintf("RDN"));
6137         Info_Number = 0x0074;
6138         Info_Mask = 0x400;
6139         Info_Sent_Flag = TRUE;
6140         break;
6141       case 20: /* Redirected Number extended */
6142         dbug(1,dprintf("RDX"));
6143         Info_Number = 0x0073;
6144         Info_Mask = 0x400;
6145         Info_Sent_Flag = TRUE;
6146         break;
6147       case 22: /* Redirecing Number  */
6148         dbug(1,dprintf("RIN"));
6149         Info_Number = 0x0076;
6150         Info_Mask = 0x400;
6151         Info_Sent_Flag = TRUE;
6152         break;
6153       default:
6154         Info_Number = 0;
6155         break;
6156       }
6157     }
6158
6159     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6160       Info_Number = 0x8000 |5;
6161       Info_Mask = 0x10;
6162       Info_Element = "";
6163     }
6164
6165     if(Info_Sent_Flag && Info_Number){
6166       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6167         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6168       }
6169     }
6170   }
6171 }
6172
6173
6174 void SendInfo(PLCI   * plci, dword Id, byte   * * parms, byte iesent)
6175 {
6176   word i;
6177   word j;
6178   word k;
6179   byte   * ie;
6180   word Info_Number;
6181   byte   * Info_Element;
6182   word Info_Mask = 0;
6183   static byte charges[5] = {4,0,0,0,0};
6184   static byte cause[] = {0x02,0x80,0x00};
6185   APPL   *appl;
6186
6187   dbug(1,dprintf("InfoParse "));
6188
6189   if(
6190         !plci->appl
6191         && !plci->State
6192         && plci->Sig.Ind!=NCR_FACILITY
6193       )
6194   {
6195     dbug(1,dprintf("NoParse "));
6196     return;
6197   }
6198   cause[2] = 0;
6199   for(i=0; i<MAXPARMSIDS; i++) {
6200     ie = parms[i];
6201     Info_Number = 0;
6202     Info_Element = ie;
6203     if(ie[0]) {
6204       switch(i) {
6205       case 0:
6206         dbug(1,dprintf("CPN "));
6207         Info_Number = 0x0070;
6208         Info_Mask   = 0x80;
6209         break;
6210       case 7: /* ESC_CAU */
6211         dbug(1,dprintf("cau(0x%x)",ie[2]));
6212         Info_Number = 0x0008;
6213         Info_Mask = 0x00;
6214         cause[2] = ie[2];
6215         Info_Element = NULL;
6216         break;
6217       case 8:  /* display      */
6218         dbug(1,dprintf("display(%d)",i));
6219         Info_Number = 0x0028;
6220         Info_Mask = 0x04;
6221         break;
6222       case 9:  /* Date display */
6223         dbug(1,dprintf("date(%d)",i));
6224         Info_Number = 0x0029;
6225         Info_Mask = 0x02;
6226         break;
6227       case 10: /* charges */
6228         for(j=0;j<4;j++) charges[1+j] = 0;
6229         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6230         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6231         Info_Number = 0x4000;
6232         Info_Mask = 0x40;
6233         Info_Element = charges;
6234         break;
6235       case 11: /* user user info */
6236         dbug(1,dprintf("uui"));
6237         Info_Number = 0x007E;
6238         Info_Mask = 0x08;
6239         break;
6240       case 12: /* congestion receiver ready */
6241         dbug(1,dprintf("clRDY"));
6242         Info_Number = 0x00B0;
6243         Info_Mask = 0x08;
6244         Info_Element = "";
6245         break;
6246       case 13: /* congestion receiver not ready */
6247         dbug(1,dprintf("clNRDY"));
6248         Info_Number = 0x00BF;
6249         Info_Mask = 0x08;
6250         Info_Element = "";
6251         break;
6252       case 15: /* Keypad Facility */
6253         dbug(1,dprintf("KEY"));
6254         Info_Number = 0x002C;
6255         Info_Mask = 0x20;
6256         break;
6257       case 16: /* Channel Id */
6258         dbug(1,dprintf("CHI"));
6259         Info_Number = 0x0018;
6260         Info_Mask = 0x100;
6261         mixer_set_bchannel_id (plci, Info_Element);
6262         break;
6263       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6264         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6265         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6266         Info_Number = 0x0008;
6267         Info_Mask = 0x01;
6268         if(cause[2] != ie[2]) Info_Element = cause;
6269         break;
6270       case 19: /* Redirected Number */
6271         dbug(1,dprintf("RDN"));
6272         Info_Number = 0x0074;
6273         Info_Mask = 0x400;
6274         break;
6275       case 22: /* Redirecing Number  */
6276         dbug(1,dprintf("RIN"));
6277         Info_Number = 0x0076;
6278         Info_Mask = 0x400;
6279         break;
6280       case 23: /* Notification Indicator  */
6281         dbug(1,dprintf("NI"));
6282         Info_Number = (word)NI;
6283         Info_Mask = 0x210;
6284         break;
6285       case 26: /* Call State  */
6286         dbug(1,dprintf("CST"));
6287         Info_Number = (word)CST;
6288         Info_Mask = 0x01; /* do with cause i.e. for now */
6289         break;
6290       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6291         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6292         Info_Number = 0x8000 |ie[3];
6293         if(iesent) Info_Mask = 0xffff;
6294         else  Info_Mask = 0x10;
6295         Info_Element = "";
6296         break;
6297       default:
6298         Info_Number  = 0;
6299         Info_Mask    = 0;
6300         Info_Element = "";
6301         break;
6302       }
6303     }
6304
6305     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6306     {
6307       for(j=0; j<max_appl; j++)
6308       {
6309         appl = &application[j];
6310         if(Info_Number
6311         && appl->Id
6312         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6313         {
6314           dbug(1,dprintf("NCR_Ind"));
6315           iesent=TRUE;
6316           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6317         }
6318       }
6319     }
6320     else if(!plci->appl)
6321     { /* overlap receiving broadcast */
6322       if(Info_Number==CPN
6323       || Info_Number==KEY
6324       || Info_Number==NI
6325       || Info_Number==DSP
6326       || Info_Number==UUI )
6327       {
6328         for(j=0; j<max_appl; j++)
6329         {
6330           if(test_c_ind_mask_bit (plci, j))
6331           {
6332             dbug(1,dprintf("Ovl_Ind"));
6333             iesent=TRUE;
6334             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6335           }
6336         }
6337       }
6338     }               /* all other signalling states */
6339     else if(Info_Number
6340     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6341     {
6342       dbug(1,dprintf("Std_Ind"));
6343       iesent=TRUE;
6344       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6345     }
6346   }
6347 }
6348
6349
6350 byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse)
6351 {
6352   word i;
6353   word j;
6354   byte   * ie;
6355   word Info_Number;
6356   byte   * Info_Element;
6357   APPL   *appl;
6358   word Info_Mask = 0;
6359   byte iesent=0;
6360
6361   if(
6362       !plci->appl
6363       && !plci->State
6364       && plci->Sig.Ind!=NCR_FACILITY
6365       && !setupParse
6366       )
6367   {
6368     dbug(1,dprintf("NoM-IEParse "));
6369     return 0;
6370   }
6371   dbug(1,dprintf("M-IEParse "));
6372
6373   for(i=0; i<MAX_MULTI_IE; i++)
6374   {
6375     ie = parms[i];
6376     Info_Number = 0;
6377     Info_Element = ie;
6378     if(ie[0])
6379     {
6380       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6381       Info_Number = (word)ie_type;
6382       Info_Mask = (word)info_mask;
6383     }
6384
6385     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6386     {
6387       for(j=0; j<max_appl; j++)
6388       {
6389         appl = &application[j];
6390         if(Info_Number
6391         && appl->Id
6392         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6393         {
6394           iesent = TRUE;
6395           dbug(1,dprintf("Mlt_NCR_Ind"));
6396           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6397         }
6398       }
6399     }
6400     else if(!plci->appl && Info_Number)
6401     {                                        /* overlap receiving broadcast */
6402       for(j=0; j<max_appl; j++)
6403       {
6404         if(test_c_ind_mask_bit (plci, j))
6405         {
6406           iesent = TRUE;
6407           dbug(1,dprintf("Mlt_Ovl_Ind"));
6408           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6409         }
6410       }
6411     }                                        /* all other signalling states */
6412     else if(Info_Number
6413     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6414     {
6415       iesent = TRUE;
6416       dbug(1,dprintf("Mlt_Std_Ind"));
6417       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6418     }
6419   }
6420   return iesent;
6421 }
6422
6423 static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6424 {
6425   word i;
6426    /* Format of multi_ssext_parms[i][]:
6427    0 byte length
6428    1 byte SSEXTIE
6429    2 byte SSEXT_REQ/SSEXT_IND
6430    3 byte length
6431    4 word SSExtCommand
6432    6... Params
6433    */
6434   if(
6435    plci
6436    && plci->State
6437    && plci->Sig.Ind!=NCR_FACILITY
6438     )
6439  for(i=0;i<MAX_MULTI_IE;i++)
6440     {
6441       if(parms[i][0]<6) continue;
6442    if(parms[i][2]==SSEXT_REQ) continue;
6443
6444    if(appl)
6445    {
6446     parms[i][0]=0; /* kill it */
6447     sendf(appl,_MANUFACTURER_I,
6448     Id,
6449     0,
6450     "dwS",
6451     _DI_MANU_ID,
6452     _DI_SSEXT_CTRL,
6453     &parms[i][3]);
6454    }
6455    else if(plci->appl)
6456    {
6457     parms[i][0]=0; /* kill it */
6458     sendf(plci->appl,_MANUFACTURER_I,
6459     Id,
6460     0,
6461     "dwS",
6462     _DI_MANU_ID,
6463     _DI_SSEXT_CTRL,
6464     &parms[i][3]);
6465    }
6466     }
6467 };
6468
6469 void nl_ind(PLCI   * plci)
6470 {
6471   byte ch;
6472   word ncci;
6473   dword Id;
6474   DIVA_CAPI_ADAPTER   * a;
6475   word NCCIcode;
6476   APPL   * APPLptr;
6477   word count;
6478   word Num;
6479   word i, ncpi_state;
6480   byte len, ncci_state;
6481   word msg;
6482   word info = 0;
6483   word fax_feature_bits;
6484   byte fax_send_edata_ack;
6485   static byte v120_header_buffer[2 + 3];
6486   static word fax_info[] = {
6487     0,                     /* T30_SUCCESS                        */
6488     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6489     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6490     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6491     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6492     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6493     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6494     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6495     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6496     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6497     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6498     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6499     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6500     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6501     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6502     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6503     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6504     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6505     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6506     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6507     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6508     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6509     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6510     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6511     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6512     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6513     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6514     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6516     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6517     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6518     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6519     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6520     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6521     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6522     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6523     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6524     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6525     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6526     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6527     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6528     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6529     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6530     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6531     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6532     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6533     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6534   };
6535
6536     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6537
6538
6539   static word rtp_info[] = {
6540     GOOD,                  /* RTP_SUCCESS                       */
6541     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6542   };
6543
6544   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6545   {
6546     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6547     0x00000000, 0x00000000, 0x00000000, 0x00000000
6548   };
6549
6550   ch = plci->NL.IndCh;
6551   a = plci->adapter;
6552   ncci = a->ch_ncci[ch];
6553   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6554   if(plci->tel) Id|=EXT_CONTROLLER;
6555   APPLptr = plci->appl;
6556   dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6557     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6558
6559   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6560
6561   if (plci->nl_remove_id)
6562   {
6563     plci->NL.RNR = 2; /* discard */
6564     dbug(1,dprintf("NL discard while remove pending"));
6565     return;
6566   }
6567   if((plci->NL.Ind &0x0f)==N_CONNECT)
6568   {
6569     if(plci->State==INC_DIS_PENDING
6570     || plci->State==OUTG_DIS_PENDING
6571     || plci->State==IDLE)
6572     {
6573       plci->NL.RNR = 2; /* discard */
6574       dbug(1,dprintf("discard n_connect"));
6575       return;
6576     }
6577     if(plci->State < INC_ACT_PENDING)
6578     {
6579       plci->NL.RNR = 1; /* flow control */
6580       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6581       return;
6582     }
6583   }
6584
6585   if(!APPLptr)                         /* no application or invalid data */
6586   {                                    /* while reloading the DSP        */
6587     dbug(1,dprintf("discard1"));
6588     plci->NL.RNR = 2;
6589     return;
6590   }
6591
6592   if (((plci->NL.Ind &0x0f) == N_UDATA)
6593      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6594         || (plci->B2_prot == 7)
6595         || (plci->B3_prot == 7)) )
6596   {
6597     plci->ncpi_buffer[0] = 0;
6598
6599     ncpi_state = plci->ncpi_state;
6600     if (plci->NL.complete == 1)
6601     {
6602       byte  * data = &plci->NL.RBuffer->P[0];
6603
6604       if ((plci->NL.RBuffer->length >= 12)
6605         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6606           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6607       {
6608         word conn_opt, ncpi_opt = 0x00;
6609 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6610
6611         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6612           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6613         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6614           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6615
6616         data++;    /* indication code */
6617         data += 2; /* timestamp */
6618         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6619           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6620         data++;    /* connected norm */
6621         conn_opt = GET_WORD(data);
6622         data += 2; /* connected options */
6623
6624         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6625
6626         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6627         {
6628           ncpi_opt |= MDM_NCPI_ECM_V42;
6629         }
6630         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6631         {
6632           ncpi_opt |= MDM_NCPI_ECM_MNP;
6633         }
6634         else
6635         {
6636           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6637         }
6638         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6639         {
6640           ncpi_opt |= MDM_NCPI_COMPRESSED;
6641         }
6642         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6643         plci->ncpi_buffer[0] = 4;
6644
6645         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6646       }
6647     }
6648     if (plci->B3_prot == 7)
6649     {
6650       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6651        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6652        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6653       {
6654         a->ncci_state[ncci] = INC_ACT_PENDING;
6655         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6656         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6657       }
6658     }
6659
6660     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6661         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6662      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6663      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6664
6665     {
6666       plci->NL.RNR = 2;
6667       return;
6668     }
6669   }
6670
6671   if(plci->NL.complete == 2)
6672     {
6673     if (((plci->NL.Ind &0x0f) == N_UDATA)
6674      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6675     {
6676       switch(plci->RData[0].P[0])
6677       {
6678
6679       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6680         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6681           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6682         break;
6683       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6684         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6685           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6686         break;
6687       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6688         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6689         break;
6690       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6691         dtmf_confirmation (Id, plci);
6692         break;
6693
6694
6695       case UDATA_INDICATION_MIXER_TAP_DATA:
6696         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6697  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6698  if (i != 0)
6699  {
6700    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6701           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6702  }
6703         break;
6704
6705
6706       case UDATA_INDICATION_MIXER_COEFS_SET:
6707         mixer_indication_coefs_set (Id, plci);
6708         break;
6709       case UDATA_INDICATION_XCONNECT_FROM:
6710         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6711         break;
6712       case UDATA_INDICATION_XCONNECT_TO:
6713         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714         break;
6715
6716
6717       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6718         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6719         break;
6720
6721
6722
6723       default:
6724         break;
6725       }
6726     }
6727     else
6728   {
6729       if ((plci->RData[0].PLength != 0)
6730      && ((plci->B2_prot == B2_V120_ASYNC)
6731       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6732       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6733     {
6734
6735       sendf(plci->appl,_DATA_B3_I,Id,0,
6736             "dwww",
6737             plci->RData[1].P,
6738               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6739             plci->RNum,
6740             plci->RFlags);
6741
6742     }
6743     else
6744     {
6745
6746       sendf(plci->appl,_DATA_B3_I,Id,0,
6747             "dwww",
6748             plci->RData[0].P,
6749             plci->RData[0].PLength,
6750             plci->RNum,
6751             plci->RFlags);
6752
6753     }
6754     }
6755     return;
6756   }
6757
6758   fax_feature_bits = 0;
6759   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6760      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6761      (plci->NL.Ind &0x0f)==N_DISC ||
6762      (plci->NL.Ind &0x0f)==N_EDATA ||
6763      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6764   {
6765     info = 0;
6766     plci->ncpi_buffer[0] = 0;
6767     switch (plci->B3_prot) {
6768     case  0: /*XPARENT*/
6769     case  1: /*T.90 NL*/
6770       break;    /* no network control protocol info - jfr */
6771     case  2: /*ISO8202*/
6772     case  3: /*X25 DCE*/
6773       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6774       plci->ncpi_buffer[0] = (byte)(i+3);
6775       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6776       plci->ncpi_buffer[2] = 0;
6777       plci->ncpi_buffer[3] = 0;
6778       break;
6779     case  4: /*T.30 - FAX*/
6780     case  5: /*T.30 - FAX*/
6781       if(plci->NL.RLength>=sizeof(T30_INFO))
6782       {
6783         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6784         len = 9;
6785         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6786         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6787         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6788         if (plci->B3_prot == 5)
6789         {
6790           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6791             i |= 0x8000; /* This is not an ECM connection */
6792           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6793             i |= 0x4000; /* This is a connection with MMR compression */
6794           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6795             i |= 0x2000; /* This is a connection with MR compression */
6796           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6797             i |= 0x0004; /* More documents */
6798           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6799             i |= 0x0002; /* Fax-polling indication */
6800         }
6801         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6802         PUT_WORD(&(plci->ncpi_buffer[3]),i);
6803         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6804         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6805         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6806         plci->ncpi_buffer[len] = 0;
6807         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6808         {
6809           plci->ncpi_buffer[len] = 20;
6810           for (i = 0; i < 20; i++)
6811             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6812         }
6813         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6814         {
6815           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
6816             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6817           else
6818             info = _FAX_PROTOCOL_ERROR;
6819         }
6820
6821         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6822           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6823         {
6824           i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6825           while (i < plci->NL.RBuffer->length)
6826             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6827         }
6828
6829         plci->ncpi_buffer[0] = len;
6830         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6831         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6832
6833         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6834  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6835          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6836           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6837          || (((plci->NL.Ind &0x0f) == N_EDATA)
6838           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6839            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6840            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6841  {
6842           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6843  }
6844  if (((plci->NL.Ind &0x0f) == N_DISC)
6845   || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6846   || (((plci->NL.Ind &0x0f) == N_EDATA)
6847    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6848  {
6849           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6850  }
6851       }
6852       break;
6853
6854     case B3_RTP:
6855       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6856       {
6857         if (plci->NL.RLength != 0)
6858         {
6859           info = rtp_info[plci->NL.RBuffer->P[0]];
6860           plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6861           for (i = 1; i < plci->NL.RLength; i++)
6862             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6863         }
6864       }
6865       break;
6866
6867     }
6868     plci->NL.RNR = 2;
6869   }
6870   switch(plci->NL.Ind &0x0f) {
6871   case N_EDATA:
6872     if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6873     {
6874       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6875         ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6876       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6877
6878       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6879        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6880        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6881        && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6882        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6883        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6884       {
6885         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6886         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6887           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6888         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6889  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6890    fax_send_edata_ack = FALSE;
6891       }
6892
6893       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6894       {
6895         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6896         {
6897         case EDATA_T30_DIS:
6898           if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6899            && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6900            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6901            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6902           {
6903             a->ncci_state[ncci] = INC_ACT_PENDING;
6904             if (plci->B3_prot == 4)
6905               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6906             else
6907               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6908             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6909           }
6910           break;
6911
6912         case EDATA_T30_TRAIN_OK:
6913           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6914            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6915            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6916           {
6917             if (plci->B3_prot == 4)
6918               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6919             else
6920               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6921             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6922           }
6923           break;
6924
6925         case EDATA_T30_EOP_CAPI:
6926           if (a->ncci_state[ncci] == CONNECTED)
6927           {
6928             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6929             a->ncci_state[ncci] = INC_DIS_PENDING;
6930             plci->ncpi_state = 0;
6931      fax_send_edata_ack = FALSE;
6932           }
6933           break;
6934         }
6935       }
6936       else
6937       {
6938         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6939         {
6940         case EDATA_T30_TRAIN_OK:
6941           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6942            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6943            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6944           {
6945             if (plci->B3_prot == 4)
6946               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6947             else
6948               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6949             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6950           }
6951           break;
6952         }
6953       }
6954       if (fax_send_edata_ack)
6955       {
6956         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6957  plci->fax_edata_ack_length = 1;
6958         start_internal_command (Id, plci, fax_edata_ack_command);
6959       }
6960     }
6961     else
6962     {
6963       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6964     }
6965     break;
6966   case N_CONNECT:
6967     if (!a->ch_ncci[ch])
6968     {
6969       ncci = get_ncci (plci, ch, 0);
6970       Id = (Id & 0xffff) | (((dword) ncci) << 16);
6971     }
6972     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6973       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6974
6975     msg = _CONNECT_B3_I;
6976     if (a->ncci_state[ncci] == IDLE)
6977       plci->channels++;
6978     else if (plci->B3_prot == 1)
6979       msg = _CONNECT_B3_T90_ACTIVE_I;
6980
6981     a->ncci_state[ncci] = INC_CON_PENDING;
6982     if(plci->B3_prot == 4)
6983       sendf(plci->appl,msg,Id,0,"s","");
6984     else
6985       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6986     break;
6987   case N_CONNECT_ACK:
6988     dbug(1,dprintf("N_connect_Ack"));
6989     if (plci->internal_command_queue[0]
6990      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6991       || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6992       || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6993     {
6994       (*(plci->internal_command_queue[0]))(Id, plci, 0);
6995       if (!plci->internal_command)
6996         next_internal_command (Id, plci);
6997       break;
6998     }
6999     msg = _CONNECT_B3_ACTIVE_I;
7000     if (plci->B3_prot == 1)
7001     {
7002       if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7003         msg = _CONNECT_B3_T90_ACTIVE_I;
7004       a->ncci_state[ncci] = INC_ACT_PENDING;
7005       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7006     }
7007     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7008     {
7009       if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7010        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7011        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7012       {
7013         a->ncci_state[ncci] = INC_ACT_PENDING;
7014         if (plci->B3_prot == 4)
7015           sendf(plci->appl,msg,Id,0,"s","");
7016         else
7017           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7018         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7019       }
7020     }
7021     else
7022     {
7023       a->ncci_state[ncci] = INC_ACT_PENDING;
7024       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7025     }
7026     if (plci->adjust_b_restore)
7027     {
7028       plci->adjust_b_restore = FALSE;
7029       start_internal_command (Id, plci, adjust_b_restore);
7030     }
7031     break;
7032   case N_DISC:
7033   case N_DISC_ACK:
7034     if (plci->internal_command_queue[0]
7035      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7036       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7037       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7038     {
7039       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7040       if (!plci->internal_command)
7041         next_internal_command (Id, plci);
7042     }
7043     ncci_state = a->ncci_state[ncci];
7044     ncci_remove (plci, ncci, FALSE);
7045
7046         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7047         /* channel, so we cannot store the state in ncci_state! The */
7048         /* information which channel we received a N_DISC is thus   */
7049         /* stored in the inc_dis_ncci_table buffer.                 */
7050     for(i=0; plci->inc_dis_ncci_table[i]; i++);
7051     plci->inc_dis_ncci_table[i] = (byte) ncci;
7052
7053       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7054     if (!plci->channels
7055      && (plci->B1_resource == 16)
7056      && (plci->State <= CONNECTED))
7057     {
7058       len = 9;
7059       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7060       PUT_WORD (&plci->ncpi_buffer[1], i);
7061       PUT_WORD (&plci->ncpi_buffer[3], 0);
7062       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7063       PUT_WORD (&plci->ncpi_buffer[5], i);
7064       PUT_WORD (&plci->ncpi_buffer[7], 0);
7065       plci->ncpi_buffer[len] = 0;
7066       plci->ncpi_buffer[0] = len;
7067       if(plci->B3_prot == 4)
7068         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7069       else
7070       {
7071
7072         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7073           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7074         {
7075           plci->ncpi_buffer[++len] = 0;
7076           plci->ncpi_buffer[++len] = 0;
7077           plci->ncpi_buffer[++len] = 0;
7078           plci->ncpi_buffer[0] = len;
7079         }
7080
7081         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7082       }
7083       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7084       plci->ncpi_state = 0;
7085       sig_req(plci,HANGUP,0);
7086       send_req(plci);
7087       plci->State = OUTG_DIS_PENDING;
7088       /* disc here */
7089     }
7090     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7091      && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7092      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7093     {
7094       if (ncci_state == IDLE)
7095       {
7096         if (plci->channels)
7097           plci->channels--;
7098         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7099           if(plci->State == SUSPENDING){
7100             sendf(plci->appl,
7101                   _FACILITY_I,
7102                   Id & 0xffffL,
7103                   0,
7104                   "ws", (word)3, "\x03\x04\x00\x00");
7105             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7106           }
7107           plci_remove(plci);
7108           plci->State=IDLE;
7109         }
7110       }
7111     }
7112     else if (plci->channels)
7113     {
7114       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7115       plci->ncpi_state = 0;
7116       if ((ncci_state == OUTG_REJ_PENDING)
7117        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7118       {
7119         sig_req(plci,HANGUP,0);
7120         send_req(plci);
7121         plci->State = OUTG_DIS_PENDING;
7122       }
7123     }
7124     break;
7125   case N_RESET:
7126     a->ncci_state[ncci] = INC_RES_PENDING;
7127     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7128     break;
7129   case N_RESET_ACK:
7130     a->ncci_state[ncci] = CONNECTED;
7131     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7132     break;
7133
7134   case N_UDATA:
7135     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7136     {
7137       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
7138       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7139       plci->NL.R = plci->RData;
7140       plci->NL.RNum = 1;
7141       return;
7142     }
7143   case N_BDATA:
7144   case N_DATA:
7145     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7146      || (a->ncci_state[ncci] == IDLE)
7147      || (a->ncci_state[ncci] == INC_DIS_PENDING))
7148     {
7149       plci->NL.RNR = 2;
7150       break;
7151     }
7152     if ((a->ncci_state[ncci] != CONNECTED)
7153      && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7154      && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7155     {
7156       dbug(1,dprintf("flow control"));
7157       plci->NL.RNR = 1; /* flow control  */
7158       channel_x_off (plci, ch, 0);
7159       break;
7160     }
7161
7162     NCCIcode = ncci | (((word)a->Id) << 8);
7163
7164                 /* count all buffers within the Application pool    */
7165                 /* belonging to the same NCCI. If this is below the */
7166                 /* number of buffers available per NCCI we accept   */
7167                 /* this packet, otherwise we reject it              */
7168     count = 0;
7169     Num = 0xffff;
7170     for(i=0; i<APPLptr->MaxBuffer; i++) {
7171       if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7172       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7173     }
7174
7175     if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7176     {
7177       dbug(3,dprintf("Flow-Control"));
7178       plci->NL.RNR = 1;
7179       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7180        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7181       {
7182         plci->NL.RNR = 2;
7183         dbug(3,dprintf("DiscardData"));
7184       } else {
7185         channel_x_off (plci, ch, 0);
7186       }
7187       break;
7188     }
7189     else
7190     {
7191       APPLptr->NCCIDataFlowCtrlTimer = 0;
7192     }
7193
7194     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7195     if(!plci->RData[0].P) {
7196       plci->NL.RNR = 1;
7197       channel_x_off (plci, ch, 0);
7198       break;
7199     }
7200
7201     APPLptr->DataNCCI[Num] = NCCIcode;
7202     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7203     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7204
7205     plci->RNum = Num;
7206     plci->RFlags = plci->NL.Ind>>4;
7207     plci->RData[0].PLength = APPLptr->MaxDataLength;
7208     plci->NL.R = plci->RData;
7209     if ((plci->NL.RLength != 0)
7210      && ((plci->B2_prot == B2_V120_ASYNC)
7211       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7212       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7213     {
7214       plci->RData[1].P = plci->RData[0].P;
7215       plci->RData[1].PLength = plci->RData[0].PLength;
7216       plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7217       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7218         plci->RData[0].PLength = 1;
7219       else
7220         plci->RData[0].PLength = 2;
7221       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7222         plci->RFlags |= 0x0010;
7223       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7224         plci->RFlags |= 0x8000;
7225       plci->NL.RNum = 2;
7226     }
7227     else
7228     {
7229       if((plci->NL.Ind &0x0f)==N_UDATA)
7230         plci->RFlags |= 0x0010;
7231
7232       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7233         plci->RFlags |= 0x0001;
7234
7235       plci->NL.RNum = 1;
7236     }
7237     break;
7238   case N_DATA_ACK:
7239     data_ack (plci, ch);
7240     break;
7241   default:
7242     plci->NL.RNR = 2;
7243     break;
7244   }
7245 }
7246
7247 /*------------------------------------------------------------------*/
7248 /* find a free PLCI                                                 */
7249 /*------------------------------------------------------------------*/
7250
7251 word get_plci(DIVA_CAPI_ADAPTER   * a)
7252 {
7253   word i,j;
7254   PLCI   * plci;
7255
7256   dump_plcis (a);
7257   for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7258   if(i==a->max_plci) {
7259     dbug(1,dprintf("get_plci: out of PLCIs"));
7260     return 0;
7261   }
7262   plci = &a->plci[i];
7263   plci->Id = (byte)(i+1);
7264
7265   plci->Sig.Id = 0;
7266   plci->NL.Id = 0;
7267   plci->sig_req = 0;
7268   plci->nl_req = 0;
7269
7270   plci->appl = NULL;
7271   plci->relatedPTYPLCI = NULL;
7272   plci->State = IDLE;
7273   plci->SuppState = IDLE;
7274   plci->channels = 0;
7275   plci->tel = 0;
7276   plci->B1_resource = 0;
7277   plci->B2_prot = 0;
7278   plci->B3_prot = 0;
7279
7280   plci->command = 0;
7281   plci->m_command = 0;
7282   init_internal_command_queue (plci);
7283   plci->number = 0;
7284   plci->req_in_start = 0;
7285   plci->req_in = 0;
7286   plci->req_out = 0;
7287   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7288   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7289   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7290
7291   plci->data_sent = FALSE;
7292   plci->send_disc = 0;
7293   plci->sig_global_req = 0;
7294   plci->sig_remove_id = 0;
7295   plci->nl_global_req = 0;
7296   plci->nl_remove_id = 0;
7297   plci->adv_nl = 0;
7298   plci->manufacturer = FALSE;
7299   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7300   plci->spoofed_msg = 0;
7301   plci->ptyState = 0;
7302   plci->cr_enquiry = FALSE;
7303   plci->hangup_flow_ctrl_timer = 0;
7304
7305   plci->ncci_ring_list = 0;
7306   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7307   clear_c_ind_mask (plci);
7308   set_group_ind_mask (plci);
7309   plci->fax_connect_info_length = 0;
7310   plci->nsf_control_bits = 0;
7311   plci->ncpi_state = 0x00;
7312   plci->ncpi_buffer[0] = 0;
7313
7314   plci->requested_options_conn = 0;
7315   plci->requested_options = 0;
7316   plci->notifiedcall = 0;
7317   plci->vswitchstate = 0;
7318   plci->vsprot = 0;
7319   plci->vsprotdialect = 0;
7320   init_b1_config (plci);
7321   dbug(1,dprintf("get_plci(%x)",plci->Id));
7322   return i+1;
7323 }
7324
7325 /*------------------------------------------------------------------*/
7326 /* put a parameter in the parameter buffer                          */
7327 /*------------------------------------------------------------------*/
7328
7329 static void add_p(PLCI   * plci, byte code, byte   * p)
7330 {
7331   word p_length;
7332
7333   p_length = 0;
7334   if(p) p_length = p[0];
7335   add_ie(plci, code, p, p_length);
7336 }
7337
7338 /*------------------------------------------------------------------*/
7339 /* put a structure in the parameter buffer                          */
7340 /*------------------------------------------------------------------*/
7341 static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7342 {
7343   if(p) add_ie(plci, code, p->info, (word)p->length);
7344 }
7345
7346 /*------------------------------------------------------------------*/
7347 /* put multiple structures in the parameter buffer                  */
7348 /*------------------------------------------------------------------*/
7349 static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7350 {
7351   byte i;
7352
7353   if(p){
7354     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7355     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7356       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7357       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7358     }
7359   }
7360 }
7361
7362 /*------------------------------------------------------------------*/
7363 /* return the channel number sent by the application in a esc_chi   */
7364 /*------------------------------------------------------------------*/
7365 static byte getChannel(API_PARSE * p)
7366 {
7367   byte i;
7368
7369   if(p){
7370     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7371       if(p->info[i]==2){
7372         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7373       }
7374     }
7375   }
7376   return 0;
7377 }
7378
7379
7380 /*------------------------------------------------------------------*/
7381 /* put an information element in the parameter buffer               */
7382 /*------------------------------------------------------------------*/
7383
7384 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7385 {
7386   word i;
7387
7388   if(!(code &0x80) && !p_length) return;
7389
7390   if(plci->req_in==plci->req_in_start) {
7391     plci->req_in +=2;
7392   }
7393   else {
7394     plci->req_in--;
7395   }
7396   plci->RBuffer[plci->req_in++] = code;
7397
7398   if(p) {
7399     plci->RBuffer[plci->req_in++] = (byte)p_length;
7400     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7401   }
7402
7403   plci->RBuffer[plci->req_in++] = 0;
7404 }
7405
7406 /*------------------------------------------------------------------*/
7407 /* put a unstructured data into the buffer                          */
7408 /*------------------------------------------------------------------*/
7409
7410 void add_d(PLCI   * plci, word length, byte   * p)
7411 {
7412   word i;
7413
7414   if(plci->req_in==plci->req_in_start) {
7415     plci->req_in +=2;
7416   }
7417   else {
7418     plci->req_in--;
7419   }
7420   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7421 }
7422
7423 /*------------------------------------------------------------------*/
7424 /* put parameters from the Additional Info parameter in the         */
7425 /* parameter buffer                                                 */
7426 /*------------------------------------------------------------------*/
7427
7428 void add_ai(PLCI   * plci, API_PARSE * ai)
7429 {
7430   word i;
7431     API_PARSE ai_parms[5];
7432
7433   for(i=0;i<5;i++) ai_parms[i].length = 0;
7434
7435   if(!ai->length)
7436     return;
7437   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7438     return;
7439
7440   add_s (plci,KEY,&ai_parms[1]);
7441   add_s (plci,UUI,&ai_parms[2]);
7442   add_ss(plci,FTY,&ai_parms[3]);
7443 }
7444
7445 /*------------------------------------------------------------------*/
7446 /* put parameter for b1 protocol in the parameter buffer            */
7447 /*------------------------------------------------------------------*/
7448
7449 word add_b1(PLCI   * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7450 {
7451     API_PARSE bp_parms[8];
7452     API_PARSE mdm_cfg[9];
7453     API_PARSE global_config[2];
7454     byte cai[256];
7455   byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7456   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7457   word i;
7458
7459     API_PARSE mdm_cfg_v18[4];
7460   word j, n, w;
7461   dword d;
7462
7463
7464   for(i=0;i<8;i++) bp_parms[i].length = 0;
7465   for(i=0;i<2;i++) global_config[i].length = 0;
7466
7467   dbug(1,dprintf("add_b1"));
7468   api_save_msg(bp, "s", &plci->B_protocol);
7469
7470   if(b_channel_info==2){
7471     plci->B1_resource = 0;
7472     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7473     add_p(plci, CAI, "\x01\x00");
7474     dbug(1,dprintf("Cai=1,0 (no resource)"));
7475     return 0;
7476   }
7477
7478   if(plci->tel == CODEC_PERMANENT) return 0;
7479   else if(plci->tel == CODEC){
7480     plci->B1_resource = 1;
7481     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7482     add_p(plci, CAI, "\x01\x01");
7483     dbug(1,dprintf("Cai=1,1 (Codec)"));
7484     return 0;
7485   }
7486   else if(plci->tel == ADV_VOICE){
7487     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7488     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7489     voice_cai[1] = plci->B1_resource;
7490     PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7491     add_p(plci, CAI, voice_cai);
7492     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7493     return 0;
7494   }
7495   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7496   if (plci->call_dir & CALL_DIR_OUT)
7497     plci->call_dir |= CALL_DIR_ORIGINATE;
7498   else if (plci->call_dir & CALL_DIR_IN)
7499     plci->call_dir |= CALL_DIR_ANSWER;
7500
7501   if(!bp->length){
7502     plci->B1_resource = 0x5;
7503     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7504     add_p(plci, CAI, "\x01\x05");
7505     return 0;
7506   }
7507
7508   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7509   if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7510   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7511   {
7512     bp_parms[6].length = 0;
7513     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7514     {
7515       dbug(1,dprintf("b-form.!"));
7516       return _WRONG_MESSAGE_FORMAT;
7517     }
7518   }
7519   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7520   {
7521     dbug(1,dprintf("b-form.!"));
7522     return _WRONG_MESSAGE_FORMAT;
7523   }
7524
7525   if(bp_parms[6].length)
7526   {
7527     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7528     {
7529       return _WRONG_MESSAGE_FORMAT;
7530     }
7531     switch(GET_WORD(global_config[0].info))
7532     {
7533     case 1:
7534       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7535       break;
7536     case 2:
7537       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7538       break;
7539     }
7540   }
7541   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7542
7543
7544   if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7545    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7546   {
7547     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7548     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7549     cai[1] = plci->B1_resource;
7550     cai[2] = 0;
7551     cai[3] = 0;
7552     cai[4] = 0;
7553     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7554     for (i = 0; i < bp_parms[3].length; i++)
7555       cai[7+i] = bp_parms[3].info[1+i];
7556     cai[0] = 6 + bp_parms[3].length;
7557     add_p(plci, CAI, cai);
7558     return 0;
7559   }
7560
7561
7562   if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7563    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7564   {
7565     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567     cai[1] = plci->B1_resource;
7568     cai[2] = 0;
7569     cai[3] = 0;
7570     cai[4] = 0;
7571     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7572     cai[0] = 6;
7573     add_p(plci, CAI, cai);
7574     return 0;
7575   }
7576
7577
7578   if ((GET_WORD(bp_parms[0].info) >= 32)
7579    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7580     && ((GET_WORD(bp_parms[0].info) != 3)
7581      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7582      || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7583   {
7584     return _B1_NOT_SUPPORTED;
7585   }
7586   plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7587     (word)(b1_facilities & ~B1_FACILITY_VOICE));
7588   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7589   cai[0] = 6;
7590   cai[1] = plci->B1_resource;
7591   for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7592
7593   if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7594    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7595    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7596   { /* B1 - modem */
7597     for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7598
7599     if (bp_parms[3].length)
7600     {
7601       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7602       {
7603         return (_WRONG_MESSAGE_FORMAT);
7604       }
7605         
7606       cai[2] = 0; /* Bit rate for adaptation */
7607
7608       dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7609
7610       PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
7611       PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7612       PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
7613       PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7614
7615       cai[3] = 0; /* Async framing parameters */
7616       switch (GET_WORD (mdm_cfg[2].info))
7617       {       /* Parity     */
7618       case 1: /* odd parity */
7619         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7620         dbug(1,dprintf("MDM: odd parity"));
7621         break;
7622
7623       case 2: /* even parity */
7624         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7625         dbug(1,dprintf("MDM: even parity"));
7626         break;
7627
7628       default:
7629         dbug(1,dprintf("MDM: no parity"));
7630         break;
7631       }
7632
7633       switch (GET_WORD (mdm_cfg[3].info))
7634       {       /* stop bits   */
7635       case 1: /* 2 stop bits */
7636         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7637         dbug(1,dprintf("MDM: 2 stop bits"));
7638         break;
7639
7640       default:
7641         dbug(1,dprintf("MDM: 1 stop bit"));
7642         break;
7643       }
7644
7645       switch (GET_WORD (mdm_cfg[1].info))
7646       {     /* char length */
7647       case 5:
7648         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7649         dbug(1,dprintf("MDM: 5 bits"));
7650         break;
7651
7652       case 6:
7653         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7654         dbug(1,dprintf("MDM: 6 bits"));
7655         break;
7656
7657       case 7:
7658         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7659         dbug(1,dprintf("MDM: 7 bits"));
7660         break;
7661
7662       default:
7663         dbug(1,dprintf("MDM: 8 bits"));
7664         break;
7665       }
7666
7667       cai[7] = 0; /* Line taking options */
7668       cai[8] = 0; /* Modulation negotiation options */
7669       cai[9] = 0; /* Modulation options */
7670
7671       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7672       {
7673         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7674         dbug(1, dprintf("MDM: Reverse direction"));
7675       }
7676
7677       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7678       {
7679         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7680         dbug(1, dprintf("MDM: Disable retrain"));
7681       }
7682
7683       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7684       {
7685         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7686         dbug(1, dprintf("MDM: Disable ring tone"));
7687       }
7688
7689       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7690       {
7691         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7692         dbug(1, dprintf("MDM: 1800 guard tone"));
7693       }
7694       else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7695       {
7696         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7697         dbug(1, dprintf("MDM: 550 guard tone"));
7698       }
7699
7700       if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7701       {
7702         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7703         dbug(1, dprintf("MDM: V100"));
7704       }
7705       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7706       {
7707         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7708         dbug(1, dprintf("MDM: IN CLASS"));
7709       }
7710       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7711       {
7712         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7713         dbug(1, dprintf("MDM: DISABLED"));
7714       }
7715       cai[0] = 20;
7716
7717       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7718        && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7719       {
7720         plci->requested_options |= 1L << PRIVATE_V18;
7721       }
7722       if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7723         plci->requested_options |= 1L << PRIVATE_VOWN;
7724
7725       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7726         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7727       {
7728         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7729         {
7730           i = 27;
7731           if (mdm_cfg[6].length >= 4)
7732           {
7733             d = GET_DWORD(&mdm_cfg[6].info[1]);
7734             cai[7] |= (byte) d;          /* line taking options */
7735             cai[9] |= (byte)(d >> 8);    /* modulation options */
7736             cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7737             cai[++i] = (byte)(d >> 24);
7738             if (mdm_cfg[6].length >= 8)
7739             {
7740               d = GET_DWORD(&mdm_cfg[6].info[5]);
7741               cai[10] |= (byte) d;        /* disabled modulations mask */
7742               cai[11] |= (byte)(d >> 8);
7743               if (mdm_cfg[6].length >= 12)
7744               {
7745                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7746                 cai[12] = (byte) d;          /* enabled modulations mask */
7747                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7748                 cai[++i] = (byte)(d >> 16);
7749                 cai[++i] = (byte)(d >> 24);
7750                 cai[++i] = 0;
7751                 if (mdm_cfg[6].length >= 14)
7752                 {
7753                   w = GET_WORD(&mdm_cfg[6].info[13]);
7754                   if (w != 0)
7755                     PUT_WORD(&cai[13], w);  /* min tx speed */
7756                   if (mdm_cfg[6].length >= 16)
7757                   {
7758                     w = GET_WORD(&mdm_cfg[6].info[15]);
7759                     if (w != 0)
7760                       PUT_WORD(&cai[15], w);  /* max tx speed */
7761                     if (mdm_cfg[6].length >= 18)
7762                     {
7763                       w = GET_WORD(&mdm_cfg[6].info[17]);
7764                       if (w != 0)
7765                         PUT_WORD(&cai[17], w);  /* min rx speed */
7766                       if (mdm_cfg[6].length >= 20)
7767                       {
7768                         w = GET_WORD(&mdm_cfg[6].info[19]);
7769                         if (w != 0)
7770                           PUT_WORD(&cai[19], w);  /* max rx speed */
7771                         if (mdm_cfg[6].length >= 22)
7772                         {
7773                           w = GET_WORD(&mdm_cfg[6].info[21]);
7774                           cai[23] = (byte)(-((short) w));  /* transmit level */
7775                           if (mdm_cfg[6].length >= 24)
7776                           {
7777                             w = GET_WORD(&mdm_cfg[6].info[23]);
7778                             cai[22] |= (byte) w;        /* info options mask */
7779                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7780                           }
7781                         }
7782                       }
7783                     }
7784                   }
7785                 }
7786               }
7787             }
7788           }
7789           cai[27] = i - 27;
7790           i++;
7791           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7792           {
7793             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7794             {
7795               for (n = 0; n < 3; n++)
7796               {
7797                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7798                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7799                   cai[i+j] = mdm_cfg_v18[n].info[j];
7800                 i += cai[i] + 1;
7801               }
7802             }
7803           }
7804           cai[0] = (byte)(i - 1);
7805         }
7806       }
7807
7808     }
7809   }
7810   if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
7811      GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
7812   {
7813     if(bp_parms[3].length){
7814       dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7815       switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
7816         case 0:
7817         case 56000:
7818           if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
7819             dbug(1,dprintf("56k sync HSCX"));
7820             cai[1] = 8;
7821             cai[2] = 0;
7822             cai[3] = 0;
7823           }
7824           else if(GET_WORD(bp_parms[0].info)==2){
7825             dbug(1,dprintf("56k async DSP"));
7826             cai[2] = 9;
7827           }
7828           break;
7829         case 50:     cai[2] = 1;  break;
7830         case 75:     cai[2] = 1;  break;
7831         case 110:    cai[2] = 1;  break;
7832         case 150:    cai[2] = 1;  break;
7833         case 200:    cai[2] = 1;  break;
7834         case 300:    cai[2] = 1;  break;
7835         case 600:    cai[2] = 1;  break;
7836         case 1200:   cai[2] = 2;  break;
7837         case 2400:   cai[2] = 3;  break;
7838         case 4800:   cai[2] = 4;  break;
7839         case 7200:   cai[2] = 10; break;
7840         case 9600:   cai[2] = 5;  break;
7841         case 12000:  cai[2] = 13; break;
7842         case 24000:  cai[2] = 0;  break;
7843         case 14400:  cai[2] = 11; break;
7844         case 19200:  cai[2] = 6;  break;
7845         case 28800:  cai[2] = 12; break;
7846         case 38400:  cai[2] = 7;  break;
7847         case 48000:  cai[2] = 8;  break;
7848         case 76:     cai[2] = 15; break;  /* 75/1200     */
7849         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7850         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7851
7852         default:
7853           return _B1_PARM_NOT_SUPPORTED;
7854       }
7855       cai[3] = 0;
7856       if (cai[1] == 13)                                        /* v.110 async */
7857       {
7858         if (bp_parms[3].length >= 8)
7859         {
7860           switch (GET_WORD (&bp_parms[3].info[3]))
7861           {       /* char length */
7862           case 5:
7863             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7864             break;
7865           case 6:
7866             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7867             break;
7868           case 7:
7869             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7870             break;
7871           }
7872           switch (GET_WORD (&bp_parms[3].info[5]))
7873           {       /* Parity     */
7874           case 1: /* odd parity */
7875             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7876             break;
7877           case 2: /* even parity */
7878             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7879             break;
7880           }
7881           switch (GET_WORD (&bp_parms[3].info[7]))
7882           {       /* stop bits   */
7883           case 1: /* 2 stop bits */
7884             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7885             break;
7886           }
7887         }
7888       }
7889     }
7890     else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7891       dbug(1,dprintf("V.110 default 56k sync"));
7892       cai[1] = 8;
7893       cai[2] = 0;
7894       cai[3] = 0;
7895     }
7896     else {
7897       dbug(1,dprintf("V.110 default 9600 async"));
7898       cai[2] = 5;
7899     }
7900   }
7901   PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7902   dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7903 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7904
7905   add_p(plci, CAI, cai);
7906   return 0;
7907 }
7908
7909 /*------------------------------------------------------------------*/
7910 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7911 /*------------------------------------------------------------------*/
7912
7913 word add_b23(PLCI   * plci, API_PARSE * bp)
7914 {
7915   word i, fax_control_bits;
7916   byte pos, len;
7917   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7918     API_PARSE bp_parms[8];
7919   API_PARSE * b1_config;
7920   API_PARSE * b2_config;
7921     API_PARSE b2_config_parms[8];
7922   API_PARSE * b3_config;
7923     API_PARSE b3_config_parms[6];
7924     API_PARSE global_config[2];
7925
7926   static byte llc[3] = {2,0,0};
7927   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7928   static byte nlc[256];
7929   static byte lli[12] = {1,1};
7930
7931   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7932   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7933
7934   const byte llc3[] = {4,3,2,2,6,6,0};
7935   const byte header[] = {0,2,3,3,0,0,0};
7936
7937   for(i=0;i<8;i++) bp_parms[i].length = 0;
7938   for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7939   for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7940
7941   lli[0] = 1;
7942   lli[1] = 1;
7943   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7944     lli[1] |= 2;
7945   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7946     lli[1] |= 4;
7947
7948   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7949     lli[1] |= 0x10;
7950     if (plci->rx_dma_descriptor <= 0) {
7951       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7952       if (plci->rx_dma_descriptor >= 0)
7953         plci->rx_dma_descriptor++;
7954     }
7955     if (plci->rx_dma_descriptor > 0) {
7956       lli[0] = 6;
7957       lli[1] |= 0x40;
7958       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7959       lli[3] = (byte)plci->rx_dma_magic;
7960       lli[4] = (byte)(plci->rx_dma_magic >>  8);
7961       lli[5] = (byte)(plci->rx_dma_magic >> 16);
7962       lli[6] = (byte)(plci->rx_dma_magic >> 24);
7963     }
7964   }
7965
7966   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7967     lli[1] |= 0x20;
7968   }
7969
7970   dbug(1,dprintf("add_b23"));
7971   api_save_msg(bp, "s", &plci->B_protocol);
7972
7973   if(!bp->length && plci->tel)
7974   {
7975     plci->adv_nl = TRUE;
7976     dbug(1,dprintf("Default adv.Nl"));
7977     add_p(plci,LLI,lli);
7978     plci->B2_prot = 1 /*XPARENT*/;
7979     plci->B3_prot = 0 /*XPARENT*/;
7980     llc[1] = 2;
7981     llc[2] = 4;
7982     add_p(plci, LLC, llc);
7983     dlc[0] = 2;
7984     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7985     add_p(plci, DLC, dlc);
7986     return 0;
7987   }
7988
7989   if(!bp->length) /*default*/
7990   {   
7991     dbug(1,dprintf("ret default"));
7992     add_p(plci,LLI,lli);
7993     plci->B2_prot = 0 /*X.75   */;
7994     plci->B3_prot = 0 /*XPARENT*/;
7995     llc[1] = 1;
7996     llc[2] = 4;
7997     add_p(plci, LLC, llc);
7998     dlc[0] = 2;
7999     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8000     add_p(plci, DLC, dlc);
8001     return 0;
8002   }
8003   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8004   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8005
8006   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8007   {
8008     bp_parms[6].length = 0;
8009     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8010     {
8011       dbug(1,dprintf("b-form.!"));
8012       return _WRONG_MESSAGE_FORMAT;
8013     }
8014   }
8015   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8016   {
8017     dbug(1,dprintf("b-form.!"));
8018     return _WRONG_MESSAGE_FORMAT;
8019   }
8020
8021   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8022   {  
8023     if(GET_WORD(bp_parms[1].info)!=1
8024     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8025     plci->adv_nl = TRUE;
8026   }
8027   else if(plci->tel) return _B2_NOT_SUPPORTED;
8028
8029
8030   if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8031    && (GET_WORD(bp_parms[2].info) == B3_RTP)
8032    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8033   {
8034     add_p(plci,LLI,lli);
8035     plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8036     plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8037     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8038     llc[2] = 4;
8039     add_p(plci, LLC, llc);
8040     dlc[0] = 2;
8041     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8042     dlc[3] = 3; /* Addr A */
8043     dlc[4] = 1; /* Addr B */
8044     dlc[5] = 7; /* modulo mode */
8045     dlc[6] = 7; /* window size */
8046     dlc[7] = 0; /* XID len Lo  */
8047     dlc[8] = 0; /* XID len Hi  */
8048     for (i = 0; i < bp_parms[4].length; i++)
8049       dlc[9+i] = bp_parms[4].info[1+i];
8050     dlc[0] = (byte)(8 + bp_parms[4].length);
8051     add_p(plci, DLC, dlc);
8052     for (i = 0; i < bp_parms[5].length; i++)
8053       nlc[1+i] = bp_parms[5].info[1+i];
8054     nlc[0] = (byte)(bp_parms[5].length);
8055     add_p(plci, NLC, nlc);
8056     return 0;
8057   }
8058
8059
8060
8061   if ((GET_WORD(bp_parms[1].info) >= 32)
8062    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8063     && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8064      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8065
8066   {
8067     return _B2_NOT_SUPPORTED;
8068   }
8069   if ((GET_WORD(bp_parms[2].info) >= 32)
8070    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8071   {
8072     return _B3_NOT_SUPPORTED;
8073   }
8074   if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8075    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8076     || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8077     || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8078   {
8079     return (add_modem_b23 (plci, bp_parms));
8080   }
8081
8082   add_p(plci,LLI,lli);
8083
8084   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8085   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8086   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8087
8088   if(bp_parms[6].length)
8089   {
8090     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8091     {
8092       return _WRONG_MESSAGE_FORMAT;
8093     }
8094     switch(GET_WORD(global_config[0].info))
8095     {
8096     case 1:
8097       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8098       break;
8099     case 2:
8100       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8101       break;
8102     }
8103   }
8104   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8105
8106
8107   if (plci->B2_prot == B2_PIAFS)
8108     llc[1] = PIAFS_CRC;
8109   else
8110 /* IMPLEMENT_PIAFS */
8111   {
8112     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8113              llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8114   }
8115   llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8116
8117   add_p(plci, LLC, llc);
8118
8119   dlc[0] = 2;
8120   PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8121                       header[GET_WORD(bp_parms[2].info)]);
8122
8123   b1_config = &bp_parms[3];
8124   nlc[0] = 0;
8125   if(plci->B3_prot == 4
8126   || plci->B3_prot == 5)
8127   {
8128     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8129     nlc[0] = sizeof(T30_INFO);
8130     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8131       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8132     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8133     if(b1_config->length>=2)
8134     {
8135       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8136     }
8137   }
8138   b2_config = &bp_parms[4];
8139
8140
8141   if (llc[1] == PIAFS_CRC)
8142   {
8143     if (plci->B3_prot != B3_TRANSPARENT)
8144     {
8145       return _B_STACK_NOT_SUPPORTED;
8146     }
8147     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8148       return _WRONG_MESSAGE_FORMAT;
8149     }
8150     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8151     dlc[3] = 0; /* Addr A */
8152     dlc[4] = 0; /* Addr B */
8153     dlc[5] = 0; /* modulo mode */
8154     dlc[6] = 0; /* window size */
8155     if (b2_config->length >= 7){
8156       dlc[ 7] = 7; 
8157       dlc[ 8] = 0; 
8158       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8159       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8160       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8161       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8162       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8163       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8164       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8165       dlc[ 0] = 15;
8166       if(b2_config->length >= 8) { /* PIAFS control abilities */
8167         dlc[ 7] = 10; 
8168         dlc[16] = 2; /* Length of PIAFS extention */
8169         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8170         dlc[18] = b2_config_parms[4].info[0]; /* value */
8171         dlc[ 0] = 18;
8172       }
8173     }
8174     else /* default values, 64K, variable, no compression */
8175     {
8176       dlc[ 7] = 7; 
8177       dlc[ 8] = 0; 
8178       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8179       dlc[10] = 0x03; /* V.42bis P0 */
8180       dlc[11] = 0;    /* V.42bis P0 */
8181       dlc[12] = 0;    /* V.42bis P1 */
8182       dlc[13] = 0;    /* V.42bis P1 */
8183       dlc[14] = 0;    /* V.42bis P2 */
8184       dlc[15] = 0;    /* V.42bis P2 */
8185     dlc[ 0] = 15;
8186     }
8187     add_p(plci, DLC, dlc);
8188   }
8189   else
8190
8191   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8192   {
8193     if (plci->B3_prot != B3_TRANSPARENT)
8194       return _B_STACK_NOT_SUPPORTED;
8195
8196     dlc[0] = 6;
8197     PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8198     dlc[3] = 0x08;
8199     dlc[4] = 0x01;
8200     dlc[5] = 127;
8201     dlc[6] = 7;
8202     if (b2_config->length != 0)
8203     {
8204       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8205         return _WRONG_MESSAGE_FORMAT;
8206       }
8207       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8208       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8209       if (b2_config->info[3] != 128)
8210       {
8211         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8212         return _B2_PARM_NOT_SUPPORTED;
8213       }
8214       dlc[5] = (byte)(b2_config->info[3] - 1);
8215       dlc[6] = b2_config->info[4];
8216       if(llc[1]==V120_V42BIS){
8217         if (b2_config->length >= 10){
8218           dlc[ 7] = 6; 
8219           dlc[ 8] = 0; 
8220           dlc[ 9] = b2_config_parms[4].info[0];
8221           dlc[10] = b2_config_parms[4].info[1];
8222           dlc[11] = b2_config_parms[5].info[0];
8223           dlc[12] = b2_config_parms[5].info[1];
8224           dlc[13] = b2_config_parms[6].info[0];
8225           dlc[14] = b2_config_parms[6].info[1];
8226           dlc[ 0] = 14;
8227           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8228           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8229           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8230         }
8231         else {
8232           dlc[ 6] = 14;
8233         }
8234       }
8235     }
8236   }
8237   else
8238   {
8239     if(b2_config->length)
8240     {
8241       dbug(1,dprintf("B2-Config"));
8242       if(llc[1]==X75_V42BIS){
8243         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8244         {
8245           return _WRONG_MESSAGE_FORMAT;
8246         }
8247       }
8248       else {
8249         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8250         {
8251           return _WRONG_MESSAGE_FORMAT;
8252         }
8253       }
8254           /* if B2 Protocol is LAPD, b2_config structure is different */
8255       if(llc[1]==6)
8256       {
8257         dlc[0] = 4;
8258         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8259         else dlc[2] = 0x01;
8260         if( (b2_config->length>=2) && (plci->B2_prot==12) )
8261         {
8262           SAPI = b2_config->info[2];    /* SAPI */
8263         }
8264         dlc[1] = SAPI;
8265         if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8266         {
8267           dlc[3] = 127;      /* Mode */
8268         }
8269         else
8270         {
8271           dlc[3] = 7;        /* Mode */
8272         }
8273    
8274         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8275         else dlc[4] = 1;
8276         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8277         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8278       }
8279       else
8280       {
8281         dlc[0] = (byte)(b2_config_parms[4].length+6);
8282         dlc[3] = b2_config->info[1];
8283         dlc[4] = b2_config->info[2];
8284         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8285           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8286           return _B2_PARM_NOT_SUPPORTED;
8287         }
8288
8289         dlc[5] = (byte)(b2_config->info[3]-1);
8290         dlc[6] = b2_config->info[4];
8291         if(dlc[6]>dlc[5]){
8292           dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8293           return _B2_PARM_NOT_SUPPORTED;
8294         }
8295  
8296         if(llc[1]==X75_V42BIS) {
8297           if (b2_config->length >= 10){
8298             dlc[ 7] = 6; 
8299             dlc[ 8] = 0; 
8300             dlc[ 9] = b2_config_parms[4].info[0];
8301             dlc[10] = b2_config_parms[4].info[1];
8302             dlc[11] = b2_config_parms[5].info[0];
8303             dlc[12] = b2_config_parms[5].info[1];
8304             dlc[13] = b2_config_parms[6].info[0];
8305             dlc[14] = b2_config_parms[6].info[1];
8306             dlc[ 0] = 14;
8307             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8308             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8309             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8310           }
8311           else {
8312             dlc[ 6] = 14;
8313           }
8314
8315         }
8316         else {
8317           PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8318           for(i=0; i<b2_config_parms[4].length; i++)
8319             dlc[11+i] = b2_config_parms[4].info[1+i];
8320         }
8321       }
8322     }
8323   }
8324   add_p(plci, DLC, dlc);
8325
8326   b3_config = &bp_parms[5];
8327   if(b3_config->length)
8328   {
8329     if(plci->B3_prot == 4 
8330     || plci->B3_prot == 5)
8331     {
8332       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8333       {
8334         return _WRONG_MESSAGE_FORMAT;
8335       }
8336       i = GET_WORD((byte   *)(b3_config_parms[0].info));
8337       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8338         ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8339       ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
8340       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8341       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8342         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8343       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8344       {
8345
8346         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8347           & (1L << PRIVATE_FAX_PAPER_FORMATS))
8348         {
8349           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8350             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8351             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8352         }
8353
8354  ((T30_INFO *)&nlc[1])->recording_properties =
8355    T30_RECORDING_WIDTH_ISO_A3 |
8356    (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8357    (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8358       }
8359       if(plci->B3_prot == 5)
8360       {
8361         if (i & 0x0002) /* Accept incoming fax-polling requests */
8362           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8363         if (i & 0x2000) /* Do not use MR compression */
8364           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8365         if (i & 0x4000) /* Do not use MMR compression */
8366           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8367         if (i & 0x8000) /* Do not use ECM */
8368           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8369         if (plci->fax_connect_info_length != 0)
8370         {
8371           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8372           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8373           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8374           fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8375             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8376         }
8377       }
8378       /* copy station id to NLC */
8379       for(i=0; i<20; i++)
8380       {
8381         if(i<b3_config_parms[2].length)
8382         {
8383           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8384         }
8385         else
8386         {
8387           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8388         }
8389       }
8390       ((T30_INFO *)&nlc[1])->station_id_len = 20;
8391       /* copy head line to NLC */
8392       if(b3_config_parms[3].length)
8393       {
8394
8395         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8396         if (pos != 0)
8397         {
8398           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8399             pos = 0;
8400           else
8401           {
8402             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8403             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8404             len = (byte)b3_config_parms[2].length;
8405             if (len > 20)
8406               len = 20;
8407             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8408             {
8409               for (i = 0; i < len; i++)
8410                 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8411               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8412               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8413             }
8414           }
8415         }
8416
8417         len = (byte)b3_config_parms[3].length;
8418         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8419           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8420         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8421         nlc[0] += (byte)(pos + len);
8422         for (i = 0; i < len; i++)
8423           ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
8424         }
8425       else
8426         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8427
8428       plci->nsf_control_bits = 0;
8429       if(plci->B3_prot == 5)
8430       {
8431         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8432          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8433         {
8434           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8435         }
8436         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8437          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8438         {
8439           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8440         }
8441         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8442           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8443         {
8444         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8445           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8446         {
8447           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8448           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8449             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8450           }
8451             len = nlc[0];
8452           pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8453    if (pos < plci->fax_connect_info_length)
8454    {
8455      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8456               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8457           }
8458    else
8459      nlc[++len] = 0;
8460    if (pos < plci->fax_connect_info_length)
8461    {
8462      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8463               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8464           }
8465    else
8466      nlc[++len] = 0;
8467           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468             & (1L << PRIVATE_FAX_NONSTANDARD))
8469           {
8470      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8471      {
8472               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8473                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8474        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476             }
8477      else
8478      {
8479               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8480               {
8481                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8482                 nlc[++len] = 0;
8483               }
8484        else
8485        {
8486                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8487                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8488          nlc[++len] = (byte)(b3_config_parms[4].length);
8489          for (i = 0; i < b3_config_parms[4].length; i++)
8490     nlc[++len] = b3_config_parms[4].info[1+i];
8491        }
8492             }
8493           }
8494             nlc[0] = len;
8495    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8496     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8497    {
8498             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8499           }
8500         }
8501       }
8502
8503       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8504       len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8505       for (i = 0; i < len; i++)
8506         plci->fax_connect_info_buffer[i] = nlc[1+i];
8507       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8508       i += ((T30_INFO *)&nlc[1])->head_line_len;
8509       while (i < nlc[0])
8510         plci->fax_connect_info_buffer[len++] = nlc[++i];
8511       plci->fax_connect_info_length = len;
8512     }
8513     else
8514     {
8515       nlc[0] = 14;
8516       if(b3_config->length!=16)
8517         return _B3_PARM_NOT_SUPPORTED;
8518       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8519       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8520         return _B3_PARM_NOT_SUPPORTED;
8521       nlc[13] = b3_config->info[13];
8522       if(GET_WORD(&b3_config->info[15])>=nlc[13])
8523         return _B3_PARM_NOT_SUPPORTED;
8524       nlc[14] = b3_config->info[15];
8525     }
8526   }
8527   else
8528   {
8529     if (plci->B3_prot == 4 
8530      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8531   }
8532   add_p(plci, NLC, nlc);
8533   return 0;
8534 }
8535
8536 /*----------------------------------------------------------------*/
8537 /*      make the same as add_b23, but only for the modem related  */
8538 /*      L2 and L3 B-Chan protocol.                                */
8539 /*                                                                */
8540 /*      Enabled L2 and L3 Configurations:                         */
8541 /*        If L1 == Modem all negotiation                          */
8542 /*          only L2 == Modem with full negotiation is allowed     */
8543 /*        If L1 == Modem async or sync                            */
8544 /*          only L2 == Transparent is allowed                     */
8545 /*        L3 == Modem or L3 == Transparent are allowed            */
8546 /*      B2 Configuration for modem:                               */
8547 /*          word : enable/disable compression, bitoptions         */
8548 /*      B3 Configuration for modem:                               */
8549 /*          empty                                                 */
8550 /*----------------------------------------------------------------*/
8551 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8552 {
8553   static byte lli[12] = {1,1};
8554   static byte llc[3] = {2,0,0};
8555   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8556     API_PARSE mdm_config[2];
8557   word i;
8558   word b2_config = 0;
8559
8560   for(i=0;i<2;i++) mdm_config[i].length = 0;
8561   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8562
8563   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8564     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8565    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8566     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8567   {
8568     return (_B_STACK_NOT_SUPPORTED);
8569   }
8570   if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8571    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8572   {
8573     return (_B_STACK_NOT_SUPPORTED);
8574   }
8575
8576   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8577   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8578
8579   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8580   {
8581     if (api_parse (&bp_parms[4].info[1],
8582                   (word)bp_parms[4].length, "w",
8583                   mdm_config))
8584     {
8585       return (_WRONG_MESSAGE_FORMAT);
8586     }
8587     b2_config = GET_WORD(mdm_config[0].info);
8588   }
8589
8590   /* OK, L2 is modem */
8591
8592   lli[0] = 1;
8593   lli[1] = 1;
8594   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8595     lli[1] |= 2;
8596   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8597     lli[1] |= 4;
8598
8599   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8600     lli[1] |= 0x10;
8601     if (plci->rx_dma_descriptor <= 0) {
8602       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8603       if (plci->rx_dma_descriptor >= 0)
8604         plci->rx_dma_descriptor++;
8605     }
8606     if (plci->rx_dma_descriptor > 0) {
8607       lli[1] |= 0x40;
8608       lli[0] = 6;
8609       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8610       lli[3] = (byte)plci->rx_dma_magic;
8611       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8612       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8613       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8614     }
8615   }
8616
8617   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8618     lli[1] |= 0x20;
8619   }
8620
8621   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8622     /*V42*/ 10 : /*V42_IN*/ 9;
8623   llc[2] = 4;                      /* pass L3 always transparent */
8624   add_p(plci, LLI, lli);
8625   add_p(plci, LLC, llc);
8626   i =  1;
8627   PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8628   i += 2;
8629   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8630   {
8631     if (bp_parms[4].length)
8632   {
8633     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8634     dlc[i++] = 3; /* Addr A */
8635     dlc[i++] = 1; /* Addr B */
8636     dlc[i++] = 7; /* modulo mode */
8637     dlc[i++] = 7; /* window size */
8638     dlc[i++] = 0; /* XID len Lo  */
8639     dlc[i++] = 0; /* XID len Hi  */
8640
8641     if (b2_config & MDM_B2_DISABLE_V42bis)
8642     {
8643       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8644     }
8645     if (b2_config & MDM_B2_DISABLE_MNP)
8646     {
8647       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8648     }
8649     if (b2_config & MDM_B2_DISABLE_TRANS)
8650     {
8651       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8652     }
8653     if (b2_config & MDM_B2_DISABLE_V42)
8654     {
8655       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8656     }
8657     if (b2_config & MDM_B2_DISABLE_COMP)
8658     {
8659       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8660     }
8661     i++;
8662   }
8663   }
8664   else
8665   {
8666     dlc[i++] = 3; /* Addr A */
8667     dlc[i++] = 1; /* Addr B */
8668     dlc[i++] = 7; /* modulo mode */
8669     dlc[i++] = 7; /* window size */
8670     dlc[i++] = 0; /* XID len Lo  */
8671     dlc[i++] = 0; /* XID len Hi  */
8672     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8673                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8674                DLC_MODEMPROT_DISABLE_V42_DETECT |
8675                DLC_MODEMPROT_DISABLE_COMPRESSION;
8676   }
8677   dlc[0] = (byte)(i - 1);
8678 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8679   add_p(plci, DLC, dlc);
8680   return (0);
8681 }
8682
8683
8684 /*------------------------------------------------------------------*/
8685 /* send a request for the signaling entity                          */
8686 /*------------------------------------------------------------------*/
8687
8688 void sig_req(PLCI   * plci, byte req, byte Id)
8689 {
8690   if(!plci) return;
8691   if(plci->adapter->adapter_disabled) return;
8692   dbug(1,dprintf("sig_req(%x)",req));
8693   if (req == REMOVE)
8694     plci->sig_remove_id = plci->Sig.Id;
8695   if(plci->req_in==plci->req_in_start) {
8696     plci->req_in +=2;
8697     plci->RBuffer[plci->req_in++] = 0;
8698   }
8699   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8700   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8701   plci->RBuffer[plci->req_in++] = req;  /* request */
8702   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8703   plci->req_in_start = plci->req_in;
8704 }
8705
8706 /*------------------------------------------------------------------*/
8707 /* send a request for the network layer entity                      */
8708 /*------------------------------------------------------------------*/
8709
8710 void nl_req_ncci(PLCI   * plci, byte req, byte ncci)
8711 {
8712   if(!plci) return;
8713   if(plci->adapter->adapter_disabled) return;
8714   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8715   if (req == REMOVE)
8716   {
8717     plci->nl_remove_id = plci->NL.Id;
8718     ncci_remove (plci, 0, (byte)(ncci != 0));
8719     ncci = 0;
8720   }
8721   if(plci->req_in==plci->req_in_start) {
8722     plci->req_in +=2;
8723     plci->RBuffer[plci->req_in++] = 0;
8724   }
8725   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8726   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8727   plci->RBuffer[plci->req_in++] = req;  /* request */
8728   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8729   plci->req_in_start = plci->req_in;
8730 }
8731
8732 void send_req(PLCI   * plci)
8733 {
8734   ENTITY   * e;
8735   word l;
8736 /*  word i; */
8737
8738   if(!plci) return;
8739   if(plci->adapter->adapter_disabled) return;
8740   channel_xmit_xon (plci);
8741
8742         /* if nothing to do, return */
8743   if(plci->req_in==plci->req_out) return;
8744   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8745
8746   if(plci->nl_req || plci->sig_req) return;
8747
8748   l = GET_WORD(&plci->RBuffer[plci->req_out]);
8749   plci->req_out += 2;
8750   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8751   plci->req_out += l;
8752   if(plci->RBuffer[plci->req_out]==1)
8753   {
8754     e = &plci->NL;
8755     plci->req_out++;
8756     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8757     e->ReqCh = plci->RBuffer[plci->req_out++];
8758     if(!(e->Id & 0x1f))
8759     {
8760       e->Id = NL_ID;
8761       plci->RBuffer[plci->req_out-4] = CAI;
8762       plci->RBuffer[plci->req_out-3] = 1;
8763       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8764       plci->RBuffer[plci->req_out-1] = 0;
8765       l+=3;
8766       plci->nl_global_req = plci->nl_req;
8767     }
8768     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8769   }
8770   else
8771   {
8772     e = &plci->Sig;
8773     if(plci->RBuffer[plci->req_out])
8774       e->Id = plci->RBuffer[plci->req_out];
8775     plci->req_out++;
8776     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8777     e->ReqCh = plci->RBuffer[plci->req_out++];
8778     if(!(e->Id & 0x1f))
8779       plci->sig_global_req = plci->sig_req;
8780     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8781   }
8782   plci->XData[0].PLength = l;
8783   e->X = plci->XData;
8784   plci->adapter->request(e);
8785   dbug(1,dprintf("send_ok"));
8786 }
8787
8788 void send_data(PLCI   * plci)
8789 {
8790   DIVA_CAPI_ADAPTER   * a;
8791   DATA_B3_DESC   * data;
8792   NCCI   *ncci_ptr;
8793   word ncci;
8794
8795   if (!plci->nl_req && plci->ncci_ring_list)
8796   {
8797     a = plci->adapter;
8798     ncci = plci->ncci_ring_list;
8799     do
8800     {
8801       ncci = a->ncci_next[ncci];
8802       ncci_ptr = &(a->ncci[ncci]);
8803       if (!(a->ncci_ch[ncci]
8804          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8805       {
8806         if (ncci_ptr->data_pending)
8807         {
8808           if ((a->ncci_state[ncci] == CONNECTED)
8809            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8810            || (plci->send_disc == ncci))
8811           {
8812             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8813             if ((plci->B2_prot == B2_V120_ASYNC)
8814              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8815              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8816             {
8817               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8818               plci->NData[1].PLength = data->Length;
8819               if (data->Flags & 0x10)
8820                 plci->NData[0].P = v120_break_header;
8821               else
8822                 plci->NData[0].P = v120_default_header;
8823               plci->NData[0].PLength = 1 ;
8824               plci->NL.XNum = 2;
8825               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8826             }
8827             else
8828             {
8829               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8830               plci->NData[0].PLength = data->Length;
8831               if (data->Flags & 0x10)
8832                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8833
8834               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8835                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8836
8837               else
8838                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8839             }
8840             plci->NL.X = plci->NData;
8841             plci->NL.ReqCh = a->ncci_ch[ncci];
8842             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8843             plci->data_sent = TRUE;
8844             plci->data_sent_ptr = data->P;
8845             a->request(&plci->NL);
8846           }
8847           else {
8848             cleanup_ncci_data (plci, ncci);
8849           }
8850         }
8851         else if (plci->send_disc == ncci)
8852         {
8853           /* dprintf("N_DISC"); */
8854           plci->NData[0].PLength = 0;
8855           plci->NL.ReqCh = a->ncci_ch[ncci];
8856           plci->NL.Req = plci->nl_req = N_DISC;
8857           a->request(&plci->NL);
8858           plci->command = _DISCONNECT_B3_R;
8859           plci->send_disc = 0;
8860         }
8861       }
8862     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8863     plci->ncci_ring_list = ncci;
8864   }
8865 }
8866
8867 void listen_check(DIVA_CAPI_ADAPTER   * a)
8868 {
8869   word i,j;
8870   PLCI   * plci;
8871   byte activnotifiedcalls = 0;
8872
8873   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8874   if (!remove_started && !a->adapter_disabled)
8875   {
8876     for(i=0;i<a->max_plci;i++)
8877     {
8878       plci = &(a->plci[i]);
8879       if(plci->notifiedcall) activnotifiedcalls++;
8880     }
8881     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8882
8883     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8884       if((j=get_plci(a))) {
8885         a->listen_active++;
8886         plci = &a->plci[j-1];
8887         plci->State = LISTENING;
8888
8889         add_p(plci,OAD,"\x01\xfd");
8890
8891         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8892
8893         add_p(plci,CAI,"\x01\xc0");
8894         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8895         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8896         add_p(plci,SHIFT|6,NULL);
8897         add_p(plci,SIN,"\x02\x00\x00");
8898         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8899         sig_req(plci,ASSIGN,DSIG_ID);
8900         send_req(plci);
8901       }
8902     }
8903   }
8904 }
8905
8906 /*------------------------------------------------------------------*/
8907 /* functions for all parameters sent in INDs                        */
8908 /*------------------------------------------------------------------*/
8909
8910 void IndParse(PLCI   * plci, word * parms_id, byte   ** parms, byte multiIEsize)
8911 {
8912   word ploc;            /* points to current location within packet */
8913   byte w;
8914   byte wlen;
8915   byte codeset,lock;
8916   byte   * in;
8917   word i;
8918   word code;
8919   word mIEindex = 0;
8920   ploc = 0;
8921   codeset = 0;
8922   lock = 0;
8923
8924   in = plci->Sig.RBuffer->P;
8925   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8926   {                            /* element but parms array is larger      */
8927     parms[i] = (byte   *)"";
8928   }
8929   for(i=0; i<multiIEsize; i++)
8930   {
8931     parms[i] = (byte   *)"";
8932   }
8933
8934   while(ploc<plci->Sig.RBuffer->length-1) {
8935
8936         /* read information element id and length                   */
8937     w = in[ploc];
8938
8939     if(w & 0x80) {
8940 /*    w &=0xf0; removed, cannot detect congestion levels */
8941 /*    upper 4 bit masked with w==SHIFT now               */
8942       wlen = 0;
8943     }
8944     else {
8945       wlen = (byte)(in[ploc+1]+1);
8946     }
8947         /* check if length valid (not exceeding end of packet)      */
8948     if((ploc+wlen) > 270) return ;
8949     if(lock & 0x80) lock &=0x7f;
8950     else codeset = lock;
8951
8952     if((w&0xf0)==SHIFT) {
8953       codeset = in[ploc];
8954       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8955       codeset &=7;
8956       lock |=0x80;
8957     }
8958     else {
8959       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8960       else code = w;
8961       code |= (codeset<<8);
8962
8963       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8964
8965       if(i<parms_id[0]+1) {
8966         if(!multiIEsize) { /* with multiIEs use next field index,          */
8967           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8968         }
8969
8970         parms[mIEindex] = &in[ploc+1];
8971         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8972         if(parms_id[i]==OAD
8973         || parms_id[i]==CONN_NR
8974         || parms_id[i]==CAD) {
8975           if(in[ploc+2] &0x80) {
8976             in[ploc+0] = (byte)(in[ploc+1]+1);
8977             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8978             in[ploc+2] = 0x80;
8979             parms[mIEindex] = &in[ploc];
8980           }
8981         }
8982         mIEindex++;       /* effects multiIEs only */
8983       }
8984     }
8985
8986     ploc +=(wlen+1);
8987   }
8988   return ;
8989 }
8990
8991 /*------------------------------------------------------------------*/
8992 /* try to match a cip from received BC and HLC                      */
8993 /*------------------------------------------------------------------*/
8994
8995 byte ie_compare(byte   * ie1, byte * ie2)
8996 {
8997   word i;
8998   if(!ie1 || ! ie2) return FALSE;
8999   if(!ie1[0]) return FALSE;
9000   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return FALSE;
9001   return TRUE;
9002 }
9003
9004 word find_cip(DIVA_CAPI_ADAPTER   * a, byte   * bc, byte   * hlc)
9005 {
9006   word i;
9007   word j;
9008
9009   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9010
9011   for(j=16;j<29 &&
9012            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9013   if(j==29) return i;
9014   return j;
9015 }
9016
9017
9018 static byte AddInfo(byte   **add_i,
9019                     byte   **fty_i,
9020                     byte   *esc_chi,
9021                     byte *facility)
9022 {
9023   byte i;
9024   byte j;
9025   byte k;
9026   byte flen;
9027   byte len=0;
9028    /* facility is a nested structure */
9029    /* FTY can be more than once      */
9030
9031   if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9032   {
9033     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9034   }
9035
9036   else
9037   {
9038     add_i[0] = (byte   *)"";
9039   }
9040   if(!fty_i[0][0])
9041   {
9042     add_i[3] = (byte   *)"";
9043   }
9044   else
9045   {    /* facility array found  */
9046     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9047     {
9048       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9049       len += fty_i[i][0];
9050       len += 2;
9051       flen=fty_i[i][0];
9052       facility[j++]=0x1c; /* copy fac IE */
9053       for(k=0;k<=flen;k++,j++)
9054       {
9055         facility[j]=fty_i[i][k];
9056 /*      dbug(1,dprintf("%x ",facility[j])); */
9057       }
9058     }
9059     facility[0] = len;
9060     add_i[3] = facility;
9061   }
9062 /*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9063   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9064   len += 4;                          /* calculate length of all */
9065   return(len);
9066 }
9067
9068 /*------------------------------------------------------------------*/
9069 /* voice and codec features                                         */
9070 /*------------------------------------------------------------------*/
9071
9072 void SetVoiceChannel(PLCI   *plci, byte   *chi, DIVA_CAPI_ADAPTER   * a)
9073 {
9074   byte voice_chi[] = "\x02\x18\x01";
9075   byte channel;
9076
9077   channel = chi[chi[0]]&0x3;
9078   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9079   voice_chi[2] = (channel) ? channel : 1;
9080   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9081   add_p(plci,ESC,voice_chi);                  /* Channel */
9082   sig_req(plci,TEL_CTRL,0);
9083   send_req(plci);
9084   if(a->AdvSignalPLCI)
9085   {
9086     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9087   }
9088 }
9089
9090 void VoiceChannelOff(PLCI   *plci)
9091 {
9092   dbug(1,dprintf("ExtDevOFF"));
9093   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9094   sig_req(plci,TEL_CTRL,0);
9095   send_req(plci);
9096   if(plci->adapter->AdvSignalPLCI)
9097   {
9098     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9099   }
9100 }
9101
9102
9103 word AdvCodecSupport(DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, byte hook_listen)
9104 {
9105   word j;
9106   PLCI   *splci;
9107
9108   /* check if hardware supports handset with hook states (adv.codec) */
9109   /* or if just a on board codec is supported                        */
9110   /* the advanced codec plci is just for internal use                */
9111
9112   /* diva Pro with on-board codec:                                   */
9113   if(a->profile.Global_Options & HANDSET)
9114   {
9115     /* new call, but hook states are already signalled */
9116     if(a->AdvCodecFLAG)
9117     {
9118       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9119       {
9120         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9121         return 0x2001; /* codec in use by another application */
9122       }
9123       if(plci!=0)
9124       {
9125         a->AdvSignalPLCI = plci;
9126         plci->tel=ADV_VOICE;
9127       }
9128       return 0;                      /* adv codec still used */
9129     }
9130     if((j=get_plci(a)))
9131     {
9132       splci = &a->plci[j-1];
9133       splci->tel = CODEC_PERMANENT;
9134       /* hook_listen indicates if a facility_req with handset/hook support */
9135       /* was sent. Otherwise if just a call on an external device was made */
9136       /* the codec will be used but the hook info will be discarded (just  */
9137       /* the external controller is in use                                 */
9138       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9139       else
9140       {
9141         splci->State = ADVANCED_VOICE_NOSIG;
9142         if(plci)
9143         {
9144           plci->spoofed_msg = SPOOFING_REQUIRED;
9145         }
9146                                                /* indicate D-ch connect if  */
9147       }                                        /* codec is connected OK     */
9148       if(plci!=0)
9149       {
9150         a->AdvSignalPLCI = plci;
9151         plci->tel=ADV_VOICE;
9152       }
9153       a->AdvSignalAppl = appl;
9154       a->AdvCodecFLAG = TRUE;
9155       a->AdvCodecPLCI = splci;
9156       add_p(splci,CAI,"\x01\x15");
9157       add_p(splci,LLI,"\x01\x00");
9158       add_p(splci,ESC,"\x02\x18\x00");
9159       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9160       splci->internal_command = PERM_COD_ASSIGN;
9161       dbug(1,dprintf("Codec Assign"));
9162       sig_req(splci,ASSIGN,DSIG_ID);
9163       send_req(splci);
9164     }
9165     else
9166     {
9167       return 0x2001; /* wrong state, no more plcis */
9168     }
9169   }
9170   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9171   {
9172     if(hook_listen) return 0x300B;               /* Facility not supported */
9173                                                  /* no hook with SCOM      */
9174     if(plci!=0) plci->tel = CODEC;
9175     dbug(1,dprintf("S/SCOM codec"));
9176     /* first time we use the scom-s codec we must shut down the internal   */
9177     /* handset application of the card. This can be done by an assign with */
9178     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9179     if(!a->scom_appl_disable){
9180       if((j=get_plci(a))) {
9181         splci = &a->plci[j-1];
9182         add_p(splci,CAI,"\x01\x80");
9183         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9185         send_req(splci);
9186         a->scom_appl_disable = TRUE;
9187       }
9188       else{
9189         return 0x2001; /* wrong state, no more plcis */
9190       }
9191     }
9192   }
9193   else return 0x300B;               /* Facility not supported */
9194
9195   return 0;
9196 }
9197
9198
9199 void CodecIdCheck(DIVA_CAPI_ADAPTER   *a, PLCI   *plci)
9200 {
9201
9202   dbug(1,dprintf("CodecIdCheck"));
9203
9204   if(a->AdvSignalPLCI == plci)
9205   {
9206     dbug(1,dprintf("PLCI owns codec"));
9207     VoiceChannelOff(a->AdvCodecPLCI);
9208     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9209     {
9210       dbug(1,dprintf("remove temp codec PLCI"));
9211       plci_remove(a->AdvCodecPLCI);
9212       a->AdvCodecFLAG  = 0;
9213       a->AdvCodecPLCI  = NULL;
9214       a->AdvSignalAppl = NULL;
9215     }
9216     a->AdvSignalPLCI = NULL;
9217   }
9218 }
9219
9220 /* -------------------------------------------------------------------
9221     Ask for physical address of card on PCI bus
9222    ------------------------------------------------------------------- */
9223 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9224                                         IDI_SYNC_REQ  * preq) {
9225   a->sdram_bar = 0;
9226   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9227     ENTITY   * e = (ENTITY   *)preq;
9228
9229     e->user[0] = a->Id - 1;
9230     preq->xdi_sdram_bar.info.bar    = 0;
9231     preq->xdi_sdram_bar.Req         = 0;
9232     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9233
9234     (*(a->request))(e);
9235
9236     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9237     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9238   }
9239 }
9240
9241 /* -------------------------------------------------------------------
9242      Ask XDI about extended features
9243    ------------------------------------------------------------------- */
9244 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9245   IDI_SYNC_REQ   * preq;
9246     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9247
9248     char features[4];
9249   preq = (IDI_SYNC_REQ   *)&buffer[0];
9250
9251   if (!diva_xdi_extended_features) {
9252     ENTITY   * e = (ENTITY   *)preq;
9253     diva_xdi_extended_features |= 0x80000000;
9254
9255     e->user[0] = a->Id - 1;
9256     preq->xdi_extended_features.Req = 0;
9257     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9258     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9259     preq->xdi_extended_features.info.features = &features[0];
9260
9261     (*(a->request))(e);
9262
9263     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9264       /*
9265          Check features located in the byte '0'
9266          */
9267       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9268         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9269       }
9270       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9271         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9272         dbug(1,dprintf("XDI provides RxDMA"));
9273       }
9274       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9275         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9276       }
9277       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9278         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9279         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9280       }
9281
9282     }
9283   }
9284
9285   diva_ask_for_xdi_sdram_bar (a, preq);
9286 }
9287
9288 /*------------------------------------------------------------------*/
9289 /* automatic law                                                    */
9290 /*------------------------------------------------------------------*/
9291 /* called from OS specific part after init time to get the Law              */
9292 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9293 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9294 {
9295   word j;
9296   PLCI   *splci;
9297
9298   if(a->automatic_law) {
9299     return;
9300   }
9301   if((j=get_plci(a))) {
9302     diva_get_extended_adapter_features (a);
9303     splci = &a->plci[j-1];
9304     a->automatic_lawPLCI = splci;
9305     a->automatic_law = 1;
9306     add_p(splci,CAI,"\x01\x80");
9307     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9308     splci->internal_command = USELAW_REQ;
9309     splci->command = 0;
9310     splci->number = 0;
9311     sig_req(splci,ASSIGN,DSIG_ID);
9312     send_req(splci);
9313   }
9314 }
9315
9316 /* called from OS specific part if an application sends an Capi20Release */
9317 word CapiRelease(word Id)
9318 {
9319   word i, j, appls_found;
9320   PLCI   *plci;
9321   APPL   *this;
9322   DIVA_CAPI_ADAPTER   *a;
9323
9324   if (!Id)
9325   {
9326     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9327     return (_WRONG_APPL_ID);
9328   }
9329
9330   this = &application[Id-1];               /* get application pointer */
9331
9332   for(i=0,appls_found=0; i<max_appl; i++)
9333   {
9334     if(application[i].Id)       /* an application has been found        */
9335     {
9336       appls_found++;
9337     }
9338   }
9339
9340   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9341   {
9342     a = &adapter[i];
9343     if (a->request)
9344     {
9345       a->Info_Mask[Id-1] = 0;
9346       a->CIP_Mask[Id-1] = 0;
9347       a->Notification_Mask[Id-1] = 0;
9348       a->codec_listen[Id-1] = NULL;
9349       a->requested_options_table[Id-1] = 0;
9350       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9351       {                                      /* with this application   */
9352         plci = &a->plci[j];
9353         if(plci->Id)                         /* if plci owns no application */
9354         {                                    /* it may be not jet connected */
9355           if(plci->State==INC_CON_PENDING
9356           || plci->State==INC_CON_ALERT)
9357           {
9358             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9359             {
9360               clear_c_ind_mask_bit (plci, (word)(Id-1));
9361               if(c_ind_mask_empty (plci))
9362               {
9363                 sig_req(plci,HANGUP,0);
9364                 send_req(plci);
9365                 plci->State = OUTG_DIS_PENDING;
9366               }
9367             }
9368           }
9369           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9370           {
9371             clear_c_ind_mask_bit (plci, (word)(Id-1));
9372             if(c_ind_mask_empty (plci))
9373             {
9374               if(!plci->appl)
9375               {
9376                 plci_remove(plci);
9377                 plci->State = IDLE;
9378               }
9379             }
9380           }
9381           if(plci->appl==this)
9382           {
9383             plci->appl = NULL;
9384             plci_remove(plci);
9385             plci->State = IDLE;
9386           }
9387         }
9388       }
9389       listen_check(a);
9390
9391       if(a->flag_dynamic_l1_down)
9392       {
9393         if(appls_found==1)            /* last application does a capi release */
9394         {
9395           if((j=get_plci(a)))
9396           {
9397             plci = &a->plci[j-1];
9398             plci->command = 0;
9399             add_p(plci,OAD,"\x01\xfd");
9400             add_p(plci,CAI,"\x01\x80");
9401             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9402             add_p(plci,SHIFT|6,NULL);
9403             add_p(plci,SIN,"\x02\x00\x00");
9404             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9405             sig_req(plci,ASSIGN,DSIG_ID);
9406             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9407             sig_req(plci,SIG_CTRL,0);
9408             send_req(plci);
9409           }
9410         }
9411       }
9412       if(a->AdvSignalAppl==this)
9413       {
9414         this->NullCREnable = FALSE;
9415         if (a->AdvCodecPLCI)
9416         {
9417           plci_remove(a->AdvCodecPLCI);
9418           a->AdvCodecPLCI->tel = 0;
9419           a->AdvCodecPLCI->adv_nl = 0;
9420         }
9421         a->AdvSignalAppl = NULL;
9422         a->AdvSignalPLCI = NULL;
9423         a->AdvCodecFLAG = 0;
9424         a->AdvCodecPLCI = NULL;
9425       }
9426     }
9427   }
9428
9429   this->Id = 0;
9430
9431   return GOOD;
9432 }
9433
9434 static word plci_remove_check(PLCI   *plci)
9435 {
9436   if(!plci) return TRUE;
9437   if(!plci->NL.Id && c_ind_mask_empty (plci))
9438   {
9439     if(plci->Sig.Id == 0xff)
9440       plci->Sig.Id = 0;
9441     if(!plci->Sig.Id)
9442     {
9443       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9444       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9445       if (plci->Id)
9446       {
9447         CodecIdCheck(plci->adapter, plci);
9448         clear_b1_config (plci);
9449         ncci_remove (plci, 0, FALSE);
9450         plci_free_msg_in_queue (plci);
9451         channel_flow_control_remove (plci);
9452         plci->Id = 0;
9453         plci->State = IDLE;
9454         plci->channels = 0;
9455         plci->appl = NULL;
9456         plci->notifiedcall = 0;
9457       }
9458       listen_check(plci->adapter);
9459       return TRUE;
9460     }
9461   }
9462   return FALSE;
9463 }
9464
9465
9466 /*------------------------------------------------------------------*/
9467
9468 static byte plci_nl_busy (PLCI   *plci)
9469 {
9470   /* only applicable for non-multiplexed protocols */
9471   return (plci->nl_req
9472     || (plci->ncci_ring_list
9473      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9474      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9475 }
9476
9477
9478 /*------------------------------------------------------------------*/
9479 /* DTMF facilities                                                  */
9480 /*------------------------------------------------------------------*/
9481
9482
9483 static struct
9484 {
9485   byte send_mask;
9486   byte listen_mask;
9487   byte character;
9488   byte code;
9489 } dtmf_digit_map[] =
9490 {
9491   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9492   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9493   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9494   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9495   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9496   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9497   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9498   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9499   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9500   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9501   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9502   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9503   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9504   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9505   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9506   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9507   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9508   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9509   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9510   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9511
9512   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9513   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9514   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9515   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9516   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9517   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9518   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9519   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9520   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9521   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9522   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9523   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9524   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9525   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9526   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9527   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9528   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9529   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9530   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9531   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9532   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9533   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9534   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9535   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9536   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9537   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9538   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9539   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9540   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9541   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9542   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9543   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9544   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9545   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9546   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9547   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9548   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9549   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9550   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9551   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9552   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9553   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9554   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9555   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9556   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9557   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9558   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9559   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9560   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9561   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9562   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9563   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9564
9565 };
9566
9567 #define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0]))
9568
9569
9570 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9571 {
9572   word min_digit_duration, min_gap_duration;
9573
9574   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9575     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9576     (char   *)(FILE_), __LINE__, enable_mask));
9577
9578   if (enable_mask != 0)
9579   {
9580     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9581     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9582     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9583     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9584     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9585     plci->NData[0].PLength = 5;
9586
9587     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9588     plci->NData[0].PLength += 2;
9589     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9590
9591   }
9592   else
9593   {
9594     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9595     plci->NData[0].PLength = 1;
9596
9597     capidtmf_recv_disable (&(plci->capidtmf_state));
9598
9599   }
9600   plci->NData[0].P = plci->internal_req_buffer;
9601   plci->NL.X = plci->NData;
9602   plci->NL.ReqCh = 0;
9603   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9604   plci->adapter->request (&plci->NL);
9605 }
9606
9607
9608 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9609 {
9610   word w, i;
9611
9612   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9613     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9614     (char   *)(FILE_), __LINE__, digit_count));
9615
9616   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9617   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9618   PUT_WORD (&plci->internal_req_buffer[1], w);
9619   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9620   PUT_WORD (&plci->internal_req_buffer[3], w);
9621   for (i = 0; i < digit_count; i++)
9622   {
9623     w = 0;
9624     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9625       && (digit_buffer[i] != dtmf_digit_map[w].character))
9626     {
9627       w++;
9628     }
9629     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9630       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9631   }
9632   plci->NData[0].PLength = 5 + digit_count;
9633   plci->NData[0].P = plci->internal_req_buffer;
9634   plci->NL.X = plci->NData;
9635   plci->NL.ReqCh = 0;
9636   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9637   plci->adapter->request (&plci->NL);
9638 }
9639
9640
9641 static void dtmf_rec_clear_config (PLCI   *plci)
9642 {
9643
9644   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9645     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9646     (char   *)(FILE_), __LINE__));
9647
9648   plci->dtmf_rec_active = 0;
9649   plci->dtmf_rec_pulse_ms = 0;
9650   plci->dtmf_rec_pause_ms = 0;
9651
9652   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9653
9654 }
9655
9656
9657 static void dtmf_send_clear_config (PLCI   *plci)
9658 {
9659
9660   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9661     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9662     (char   *)(FILE_), __LINE__));
9663
9664   plci->dtmf_send_requests = 0;
9665   plci->dtmf_send_pulse_ms = 0;
9666   plci->dtmf_send_pause_ms = 0;
9667 }
9668
9669
9670 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9671 {
9672
9673   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9674     UnMapId (Id), (char   *)(FILE_), __LINE__));
9675
9676   while (plci->dtmf_send_requests != 0)
9677     dtmf_confirmation (Id, plci);
9678 }
9679
9680
9681 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9682 {
9683
9684   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9685     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9686
9687   return (GOOD);
9688 }
9689
9690
9691 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9692 {
9693   word Info;
9694
9695   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9696     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9697
9698   Info = GOOD;
9699   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9700   {
9701     switch (plci->adjust_b_state)
9702     {
9703     case ADJUST_B_RESTORE_DTMF_1:
9704       plci->internal_command = plci->adjust_b_command;
9705       if (plci_nl_busy (plci))
9706       {
9707         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9708         break;
9709       }
9710       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9711       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9712       break;
9713     case ADJUST_B_RESTORE_DTMF_2:
9714       if ((Rc != OK) && (Rc != OK_FC))
9715       {
9716         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9717           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9718         Info = _WRONG_STATE;
9719         break;
9720       }
9721       break;
9722     }
9723   }
9724   return (Info);
9725 }
9726
9727
9728 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9729 {
9730   word internal_command, Info;
9731   byte mask;
9732     byte result[4];
9733
9734   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9735     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9736     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9737     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9738
9739   Info = GOOD;
9740   result[0] = 2;
9741   PUT_WORD (&result[1], DTMF_SUCCESS);
9742   internal_command = plci->internal_command;
9743   plci->internal_command = 0;
9744   mask = 0x01;
9745   switch (plci->dtmf_cmd)
9746   {
9747
9748   case DTMF_LISTEN_TONE_START:
9749     mask <<= 1;
9750   case DTMF_LISTEN_MF_START:
9751     mask <<= 1;
9752
9753   case DTMF_LISTEN_START:
9754     switch (internal_command)
9755     {
9756     default:
9757       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9758         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9759     case DTMF_COMMAND_1:
9760       if (adjust_b_process (Id, plci, Rc) != GOOD)
9761       {
9762         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9763           UnMapId (Id), (char   *)(FILE_), __LINE__));
9764         Info = _FACILITY_NOT_SUPPORTED;
9765         break;
9766       }
9767       if (plci->internal_command)
9768         return;
9769     case DTMF_COMMAND_2:
9770       if (plci_nl_busy (plci))
9771       {
9772         plci->internal_command = DTMF_COMMAND_2;
9773         return;
9774       }
9775       plci->internal_command = DTMF_COMMAND_3;
9776       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9777       return;
9778     case DTMF_COMMAND_3:
9779       if ((Rc != OK) && (Rc != OK_FC))
9780       {
9781         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9782           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9783         Info = _FACILITY_NOT_SUPPORTED;
9784         break;
9785       }
9786
9787       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9788
9789       plci->dtmf_rec_active |= mask;
9790       break;
9791     }
9792     break;
9793
9794
9795   case DTMF_LISTEN_TONE_STOP:
9796     mask <<= 1;
9797   case DTMF_LISTEN_MF_STOP:
9798     mask <<= 1;
9799
9800   case DTMF_LISTEN_STOP:
9801     switch (internal_command)
9802     {
9803     default:
9804       plci->dtmf_rec_active &= ~mask;
9805       if (plci->dtmf_rec_active)
9806         break;
9807 /*
9808     case DTMF_COMMAND_1:
9809       if (plci->dtmf_rec_active)
9810       {
9811         if (plci_nl_busy (plci))
9812         {
9813           plci->internal_command = DTMF_COMMAND_1;
9814           return;
9815         }
9816         plci->dtmf_rec_active &= ~mask;
9817         plci->internal_command = DTMF_COMMAND_2;
9818         dtmf_enable_receiver (plci, FALSE);
9819         return;
9820       }
9821       Rc = OK;
9822     case DTMF_COMMAND_2:
9823       if ((Rc != OK) && (Rc != OK_FC))
9824       {
9825         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9826           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9827         Info = _FACILITY_NOT_SUPPORTED;
9828         break;
9829       }
9830 */
9831       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9832         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9833     case DTMF_COMMAND_3:
9834       if (adjust_b_process (Id, plci, Rc) != GOOD)
9835       {
9836         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9837           UnMapId (Id), (char   *)(FILE_), __LINE__));
9838         Info = _FACILITY_NOT_SUPPORTED;
9839         break;
9840       }
9841       if (plci->internal_command)
9842         return;
9843       break;
9844     }
9845     break;
9846
9847
9848   case DTMF_SEND_TONE:
9849     mask <<= 1;
9850   case DTMF_SEND_MF:
9851     mask <<= 1;
9852
9853   case DTMF_DIGITS_SEND:
9854     switch (internal_command)
9855     {
9856     default:
9857       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9858         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9859         DTMF_COMMAND_1);
9860     case DTMF_COMMAND_1:
9861       if (adjust_b_process (Id, plci, Rc) != GOOD)
9862       {
9863         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9864           UnMapId (Id), (char   *)(FILE_), __LINE__));
9865         Info = _FACILITY_NOT_SUPPORTED;
9866         break;
9867       }
9868       if (plci->internal_command)
9869         return;
9870     case DTMF_COMMAND_2:
9871       if (plci_nl_busy (plci))
9872       {
9873         plci->internal_command = DTMF_COMMAND_2;
9874         return;
9875       }
9876       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9877       plci->internal_command = DTMF_COMMAND_3;
9878       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9879       return;
9880     case DTMF_COMMAND_3:
9881       if ((Rc != OK) && (Rc != OK_FC))
9882       {
9883         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9884           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9885         if (plci->dtmf_send_requests != 0)
9886           (plci->dtmf_send_requests)--;
9887         Info = _FACILITY_NOT_SUPPORTED;
9888         break;
9889       }
9890       return;
9891     }
9892     break;
9893   }
9894   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9895     "wws", Info, SELECTOR_DTMF, result);
9896 }
9897
9898
9899 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9900 {
9901   word Info;
9902   word i, j;
9903   byte mask;
9904     API_PARSE dtmf_parms[5];
9905     byte result[40];
9906
9907   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9908     UnMapId (Id), (char   *)(FILE_), __LINE__));
9909
9910   Info = GOOD;
9911   result[0] = 2;
9912   PUT_WORD (&result[1], DTMF_SUCCESS);
9913   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9914   {
9915     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9916       UnMapId (Id), (char   *)(FILE_), __LINE__));
9917     Info = _FACILITY_NOT_SUPPORTED;
9918   }
9919   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9920   {
9921     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9922       UnMapId (Id), (char   *)(FILE_), __LINE__));
9923     Info = _WRONG_MESSAGE_FORMAT;
9924   }
9925
9926   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9927     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9928   {
9929     if (!((a->requested_options_table[appl->Id-1])
9930         & (1L << PRIVATE_DTMF_TONE)))
9931     {
9932       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9933         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9934       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9935     }
9936     else
9937     {
9938       for (i = 0; i < 32; i++)
9939         result[4 + i] = 0;
9940       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9941       {
9942         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9943         {
9944           if (dtmf_digit_map[i].listen_mask != 0)
9945             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9946         }
9947       }
9948       else
9949       {
9950         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9951         {
9952           if (dtmf_digit_map[i].send_mask != 0)
9953             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9954         }
9955       }
9956       result[0] = 3 + 32;
9957       result[3] = 32;
9958     }
9959   }
9960
9961   else if (plci == NULL)
9962   {
9963     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9964       UnMapId (Id), (char   *)(FILE_), __LINE__));
9965     Info = _WRONG_IDENTIFIER;
9966   }
9967   else
9968   {
9969     if (!plci->State
9970      || !plci->NL.Id || plci->nl_remove_id)
9971     {
9972       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9973         UnMapId (Id), (char   *)(FILE_), __LINE__));
9974       Info = _WRONG_STATE;
9975     }
9976     else
9977     {
9978       plci->command = 0;
9979       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9980       mask = 0x01;
9981       switch (plci->dtmf_cmd)
9982       {
9983
9984       case DTMF_LISTEN_TONE_START:
9985       case DTMF_LISTEN_TONE_STOP:
9986         mask <<= 1;
9987       case DTMF_LISTEN_MF_START:
9988       case DTMF_LISTEN_MF_STOP:
9989         mask <<= 1;
9990         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9991           & (1L << PRIVATE_DTMF_TONE)))
9992         {
9993           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9994             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9995           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9996           break;
9997         }
9998
9999       case DTMF_LISTEN_START:
10000       case DTMF_LISTEN_STOP:
10001         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10002          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10003         {
10004           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10005             UnMapId (Id), (char   *)(FILE_), __LINE__));
10006           Info = _FACILITY_NOT_SUPPORTED;
10007           break;
10008         }
10009         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10010         {
10011           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10012           {
10013             plci->dtmf_rec_pulse_ms = 0;
10014             plci->dtmf_rec_pause_ms = 0;
10015           }
10016           else
10017           {
10018             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10019             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10020           }
10021         }
10022         start_internal_command (Id, plci, dtmf_command);
10023         return (FALSE);
10024
10025
10026       case DTMF_SEND_TONE:
10027         mask <<= 1;
10028       case DTMF_SEND_MF:
10029         mask <<= 1;
10030         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10031           & (1L << PRIVATE_DTMF_TONE)))
10032         {
10033           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10034             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10035           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10036           break;
10037         }
10038
10039       case DTMF_DIGITS_SEND:
10040         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10041         {
10042           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10043             UnMapId (Id), (char   *)(FILE_), __LINE__));
10044           Info = _WRONG_MESSAGE_FORMAT;
10045           break;
10046         }
10047         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10048         {
10049           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10050           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10051         }
10052         i = 0;
10053         j = 0;
10054         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10055         {
10056           j = 0;
10057           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10058             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10059              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10060           {
10061             j++;
10062           }
10063           i++;
10064         }
10065         if (j == DTMF_DIGIT_MAP_ENTRIES)
10066         {
10067           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10068             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10069           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10070           break;
10071         }
10072         if (plci->dtmf_send_requests >=
10073           sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0]))
10074         {
10075           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10076             UnMapId (Id), (char   *)(FILE_), __LINE__));
10077           Info = _WRONG_STATE;
10078           break;
10079         }
10080         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10081         start_internal_command (Id, plci, dtmf_command);
10082         return (FALSE);
10083
10084       default:
10085         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10086           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10087         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10088       }
10089     }
10090   }
10091   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10092     "wws", Info, SELECTOR_DTMF, result);
10093   return (FALSE);
10094 }
10095
10096
10097 static void dtmf_confirmation (dword Id, PLCI   *plci)
10098 {
10099   word Info;
10100   word i;
10101     byte result[4];
10102
10103   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10104     UnMapId (Id), (char   *)(FILE_), __LINE__));
10105
10106   Info = GOOD;
10107   result[0] = 2;
10108   PUT_WORD (&result[1], DTMF_SUCCESS);
10109   if (plci->dtmf_send_requests != 0)
10110   {
10111     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10112       "wws", GOOD, SELECTOR_DTMF, result);
10113     (plci->dtmf_send_requests)--;
10114     for (i = 0; i < plci->dtmf_send_requests; i++)
10115       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10116   }
10117 }
10118
10119
10120 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10121 {
10122   word i, j, n;
10123
10124   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10125     UnMapId (Id), (char   *)(FILE_), __LINE__));
10126
10127   n = 0;
10128   for (i = 1; i < length; i++)
10129   {
10130     j = 0;
10131     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10132       && ((msg[i] != dtmf_digit_map[j].code)
10133        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10134     {
10135       j++;
10136     }
10137     if (j < DTMF_DIGIT_MAP_ENTRIES)
10138     {
10139
10140       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10141        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10142        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10143       {
10144         if (n + 1 == i)
10145         {
10146           for (i = length; i > n + 1; i--)
10147             msg[i] = msg[i - 1];
10148           length++;
10149           i++;
10150         }
10151         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10152       }
10153       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10154
10155       msg[++n] = dtmf_digit_map[j].character;
10156     }
10157   }
10158   if (n != 0)
10159   {
10160     msg[0] = (byte) n;
10161     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10162   }
10163 }
10164
10165
10166 /*------------------------------------------------------------------*/
10167 /* DTMF parameters                                                  */
10168 /*------------------------------------------------------------------*/
10169
10170 static void dtmf_parameter_write (PLCI   *plci)
10171 {
10172   word i;
10173     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10174
10175   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10176     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10177     (char   *)(FILE_), __LINE__));
10178
10179   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10180   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10181   for (i = 0; i < plci->dtmf_parameter_length; i++)
10182     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10183   add_p (plci, FTY, parameter_buffer);
10184   sig_req (plci, TEL_CTRL, 0);
10185   send_req (plci);
10186 }
10187
10188
10189 static void dtmf_parameter_clear_config (PLCI   *plci)
10190 {
10191
10192   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10193     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10194     (char   *)(FILE_), __LINE__));
10195
10196   plci->dtmf_parameter_length = 0;
10197 }
10198
10199
10200 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10201 {
10202
10203   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10204     UnMapId (Id), (char   *)(FILE_), __LINE__));
10205
10206 }
10207
10208
10209 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10210 {
10211
10212   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10213     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10214
10215   return (GOOD);
10216 }
10217
10218
10219 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10220 {
10221   word Info;
10222
10223   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10224     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10225
10226   Info = GOOD;
10227   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10228    && (plci->dtmf_parameter_length != 0))
10229   {
10230     switch (plci->adjust_b_state)
10231     {
10232     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10233       plci->internal_command = plci->adjust_b_command;
10234       if (plci->sig_req)
10235       {
10236         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10237         break;
10238       }
10239       dtmf_parameter_write (plci);
10240       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10241       break;
10242     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10243       if ((Rc != OK) && (Rc != OK_FC))
10244       {
10245         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10246           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10247         Info = _WRONG_STATE;
10248         break;
10249       }
10250       break;
10251     }
10252   }
10253   return (Info);
10254 }
10255
10256
10257 /*------------------------------------------------------------------*/
10258 /* Line interconnect facilities                                     */
10259 /*------------------------------------------------------------------*/
10260
10261
10262 LI_CONFIG   *li_config_table;
10263 word li_total_channels;
10264
10265
10266 /*------------------------------------------------------------------*/
10267 /* translate a CHI information element to a channel number          */
10268 /* returns 0xff - any channel                                       */
10269 /*         0xfe - chi wrong coding                                  */
10270 /*         0xfd - D-channel                                         */
10271 /*         0x00 - no channel                                        */
10272 /*         else channel number / PRI: timeslot                      */
10273 /* if channels is provided we accept more than one channel.         */
10274 /*------------------------------------------------------------------*/
10275
10276 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10277 {
10278   int p;
10279   int i;
10280   dword map;
10281   byte excl;
10282   byte ofs;
10283   byte ch;
10284
10285   if (pchannelmap) *pchannelmap = 0;
10286   if(!chi[0]) return 0xff;
10287   excl = 0;
10288
10289   if(chi[1] & 0x20) {
10290     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10291     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10292     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10293     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10294     if(chi[1] &0x08) excl = 0x40;
10295
10296         /* int. id present */
10297     if(chi[1] &0x40) {
10298       p=i+1;
10299       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10300       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10301     }
10302
10303         /* coding standard, Number/Map, Channel Type */
10304     p=i+1;
10305     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10306     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10307     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10308
10309         /* Number/Map */
10310     if(chi[p] &0x10) {
10311
10312         /* map */
10313       if((chi[0]-p)==4) ofs = 0;
10314       else if((chi[0]-p)==3) ofs = 1;
10315       else return 0xfe;
10316       ch = 0;
10317       map = 0;
10318       for(i=0; i<4 && p<chi[0]; i++) {
10319         p++;
10320         ch += 8;
10321         map <<= 8;
10322         if(chi[p]) {
10323           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10324           map |= chi[p];
10325         }
10326       }
10327       ch += ofs;
10328       map <<= ofs;
10329     }
10330     else {
10331
10332         /* number */
10333       p=i+1;
10334       ch = chi[p] &0x3f;
10335       if(pchannelmap) {
10336         if((byte)(chi[0]-p)>30) return 0xfe;
10337         map = 0;
10338         for(i=p; i<=chi[0]; i++) {
10339           if ((chi[i] &0x7f) > 31) return 0xfe;
10340           map |= (1L << (chi[i] &0x7f));
10341         }
10342       }
10343       else {
10344         if(p!=chi[0]) return 0xfe;
10345         if (ch > 31) return 0xfe;
10346         map = (1L << ch);
10347       }
10348       if(chi[p] &0x40) return 0xfe;
10349     }
10350     if (pchannelmap) *pchannelmap = map;
10351     else if (map != ((dword)(1L << ch))) return 0xfe;
10352     return (byte)(excl | ch);
10353   }
10354   else {  /* not PRI */
10355     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10356     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10357     if(chi[1] &0x08) excl = 0x40;
10358
10359     switch(chi[1] |0x98) {
10360     case 0x98: return 0;
10361     case 0x99:
10362       if (pchannelmap) *pchannelmap = 2;
10363       return excl |1;
10364     case 0x9a:
10365       if (pchannelmap) *pchannelmap = 4;
10366       return excl |2;
10367     case 0x9b: return 0xff;
10368     case 0x9c: return 0xfd; /* d-ch */
10369     default: return 0xfe;
10370     }
10371   }
10372 }
10373
10374
10375 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10376 {
10377   DIVA_CAPI_ADAPTER   *a;
10378   PLCI   *splci;
10379   byte old_id;
10380
10381   a = plci->adapter;
10382   old_id = plci->li_bchannel_id;
10383   if (a->li_pri)
10384   {
10385     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10386       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10387     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10388     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10389       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10390   }
10391   else
10392   {
10393     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10394     {
10395       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10396         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10397       plci->li_bchannel_id = bchannel_id & 0x03;
10398       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10399       {
10400         splci = a->AdvSignalPLCI;
10401         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10402         {
10403           if ((splci->li_bchannel_id != 0)
10404            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10405           {
10406             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10407           }
10408           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10409           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10410           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10411             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10412             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10413         }
10414       }
10415       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10416         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10417     }
10418   }
10419   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10420    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10421   {
10422     mixer_clear_config (plci);
10423   }
10424   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10425     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10426     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10427 }
10428
10429
10430 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10431 {
10432   DIVA_CAPI_ADAPTER   *a;
10433   PLCI   *splci;
10434   byte ch, old_id;
10435
10436   a = plci->adapter;
10437   old_id = plci->li_bchannel_id;
10438   ch = chi_to_channel (chi, NULL);
10439   if (!(ch & 0x80))
10440   {
10441     if (a->li_pri)
10442     {
10443       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10444         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10445       plci->li_bchannel_id = (ch & 0x1f) + 1;
10446       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10447         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10448     }
10449     else
10450     {
10451       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10452       {
10453         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10454           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10455         plci->li_bchannel_id = ch & 0x1f;
10456         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10457         {
10458           splci = a->AdvSignalPLCI;
10459           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10460           {
10461             if ((splci->li_bchannel_id != 0)
10462              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10463             {
10464               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10465             }
10466             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10467             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10468             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10469               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10470               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10471           }
10472         }
10473         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10474           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10475       }
10476     }
10477   }
10478   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10479    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10480   {
10481     mixer_clear_config (plci);
10482   }
10483   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10484     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10485     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10486 }
10487
10488
10489 #define MIXER_MAX_DUMP_CHANNELS 34
10490
10491 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10492 {
10493 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10494   word n, i, j;
10495   char *p;
10496     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10497
10498   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10499     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10500
10501   for (i = 0; i < li_total_channels; i++)
10502   {
10503     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10504     if (li_config_table[i].chflags != 0)
10505       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10506     else
10507     {
10508       for (j = 0; j < li_total_channels; j++)
10509       {
10510         if (((li_config_table[i].flag_table[j]) != 0)
10511          || ((li_config_table[j].flag_table[i]) != 0))
10512         {
10513           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10514         }
10515         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10516          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10517         {
10518           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10519         }
10520       }
10521     }
10522   }
10523   for (i = 0; i < li_total_channels; i++)
10524   {
10525     for (j = 0; j < li_total_channels; j++)
10526     {
10527       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10528       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10529         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10530     }
10531   }
10532   for (n = 0; n < li_total_channels; n++)
10533   {
10534     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10535     {
10536       for (i = 0; i < li_total_channels; i++)
10537       {
10538         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10539         {
10540           for (j = 0; j < li_total_channels; j++)
10541           {
10542             li_config_table[i].coef_table[j] |=
10543               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10544           }
10545         }
10546       }
10547     }
10548   }
10549   for (i = 0; i < li_total_channels; i++)
10550   {
10551     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10552     {
10553       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10554       for (j = 0; j < li_total_channels; j++)
10555       {
10556         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10557           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10558       }
10559       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10560         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10561     }
10562   }
10563   for (i = 0; i < li_total_channels; i++)
10564   {
10565     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10566     {
10567       for (j = 0; j < li_total_channels; j++)
10568       {
10569         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10570           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10571         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10572           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10573         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10574           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10575         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10576           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10577       }
10578       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10579       {
10580         for (j = 0; j < li_total_channels; j++)
10581         {
10582           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10583           {
10584             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10585             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10586               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10587           }
10588         }
10589       }
10590       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10591       {
10592         for (j = 0; j < li_total_channels; j++)
10593         {
10594           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10595             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10596         }
10597       }
10598       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10599       {
10600         for (j = 0; j < li_total_channels; j++)
10601         {
10602           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10603           {
10604             for (n = 0; n < li_total_channels; n++)
10605             {
10606               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10607               {
10608                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10609                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10610                 {
10611                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10612                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10613                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10614                 }
10615                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10616                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10617               }
10618             }
10619           }
10620         }
10621       }
10622     }
10623   }
10624   for (i = 0; i < li_total_channels; i++)
10625   {
10626     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10627     {
10628       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10629         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10630       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10631         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10632       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10633         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10634       for (j = 0; j < li_total_channels; j++)
10635       {
10636         if ((li_config_table[i].flag_table[j] &
10637           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10638          || (li_config_table[j].flag_table[i] &
10639           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10640         {
10641           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10642         }
10643         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10644           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10645         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10646           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10647       }
10648       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10649       {
10650         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10651         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10652       }
10653     }
10654   }
10655   for (i = 0; i < li_total_channels; i++)
10656   {
10657     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10658     {
10659       j = 0;
10660       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10661         j++;
10662       if (j < li_total_channels)
10663       {
10664         for (j = 0; j < li_total_channels; j++)
10665         {
10666           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10667           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10668             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10669         }
10670       }
10671     }
10672   }
10673   n = li_total_channels;
10674   if (n > MIXER_MAX_DUMP_CHANNELS)
10675     n = MIXER_MAX_DUMP_CHANNELS;
10676   p = hex_line;
10677   for (j = 0; j < n; j++)
10678   {
10679     if ((j & 0x7) == 0)
10680       *(p++) = ' ';
10681     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10682     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10683   }
10684   *p = '\0';
10685   dbug (1, dprintf ("[%06lx] CURRENT %s",
10686     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10687   p = hex_line;
10688   for (j = 0; j < n; j++)
10689   {
10690     if ((j & 0x7) == 0)
10691       *(p++) = ' ';
10692     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10693     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10694   }
10695   *p = '\0';
10696   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10697     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10698   p = hex_line;
10699   for (j = 0; j < n; j++)
10700   {
10701     if ((j & 0x7) == 0)
10702       *(p++) = ' ';
10703     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10704     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10705   }
10706   *p = '\0';
10707   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10708     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10709   for (i = 0; i < n; i++)
10710   {
10711     p = hex_line;
10712     for (j = 0; j < n; j++)
10713     {
10714       if ((j & 0x7) == 0)
10715         *(p++) = ' ';
10716       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10717       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10718     }
10719     *p = '\0';
10720     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10721       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10722   }
10723   for (i = 0; i < n; i++)
10724   {
10725     p = hex_line;
10726     for (j = 0; j < n; j++)
10727     {
10728       if ((j & 0x7) == 0)
10729         *(p++) = ' ';
10730       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10731       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10732     }
10733     *p = '\0';
10734     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10735       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10736   }
10737 }
10738
10739
10740 static struct
10741 {
10742   byte mask;
10743   byte line_flags;
10744 } mixer_write_prog_pri[] =
10745 {
10746   { LI_COEF_CH_CH, 0 },
10747   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10748   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10749   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10750 };
10751
10752 static struct
10753 {
10754   byte from_ch;
10755   byte to_ch;
10756   byte mask;
10757   byte xconnect_override;
10758 } mixer_write_prog_bri[] =
10759 {
10760   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10761   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10762   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10763   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10764   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10765   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10766   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10767   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10768   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10769   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10770   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10771   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10772   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10773   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10774   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10775   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10776   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10777   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10778   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10779   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10780   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10781   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10782   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10783   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10784   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10785   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10786   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10787   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10788   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10789   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10790   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10791   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10792   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10793   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10794   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10795   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10796 };
10797
10798 static byte mixer_swapped_index_bri[] =
10799 {
10800   18,  /* B      to B      */
10801   19,  /* Alt B  to B      */
10802   20,  /* PC     to B      */
10803   21,  /* Alt PC to B      */
10804   22,  /* IC     to B      */
10805   23,  /* Alt IC to B      */
10806   24,  /* B      to PC     */
10807   25,  /* Alt B  to PC     */
10808   26,  /* PC     to PC     */
10809   27,  /* Alt PC to PC     */
10810   28,  /* IC     to PC     */
10811   29,  /* Alt IC to PC     */
10812   30,  /* B      to IC     */
10813   31,  /* Alt B  to IC     */
10814   32,  /* PC     to IC     */
10815   33,  /* Alt PC to IC     */
10816   34,  /* IC     to IC     */
10817   35,  /* Alt IC to IC     */
10818   0,   /* Alt B  to Alt B  */
10819   1,   /* B      to Alt B  */
10820   2,   /* Alt PC to Alt B  */
10821   3,   /* PC     to Alt B  */
10822   4,   /* Alt IC to Alt B  */
10823   5,   /* IC     to Alt B  */
10824   6,   /* Alt B  to Alt PC */
10825   7,   /* B      to Alt PC */
10826   8,   /* Alt PC to Alt PC */
10827   9,   /* PC     to Alt PC */
10828   10,  /* Alt IC to Alt PC */
10829   11,  /* IC     to Alt PC */
10830   12,  /* Alt B  to Alt IC */
10831   13,  /* B      to Alt IC */
10832   14,  /* Alt PC to Alt IC */
10833   15,  /* PC     to Alt IC */
10834   16,  /* Alt IC to Alt IC */
10835   17   /* IC     to Alt IC */
10836 };
10837
10838 static struct
10839 {
10840   byte mask;
10841   byte from_pc;
10842   byte to_pc;
10843 } xconnect_write_prog[] =
10844 {
10845   { LI_COEF_CH_CH, FALSE, FALSE },
10846   { LI_COEF_CH_PC, FALSE, TRUE },
10847   { LI_COEF_PC_CH, TRUE, FALSE },
10848   { LI_COEF_PC_PC, TRUE, TRUE }
10849 };
10850
10851
10852 static void xconnect_query_addresses (PLCI   *plci)
10853 {
10854   DIVA_CAPI_ADAPTER   *a;
10855   word w, ch;
10856   byte   *p;
10857
10858   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10859     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10860     (char   *)(FILE_), __LINE__));
10861
10862   a = plci->adapter;
10863   if (a->li_pri && ((plci->li_bchannel_id == 0)
10864    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10865   {
10866     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10867       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10868       (char   *)(FILE_), __LINE__));
10869     return;
10870   }
10871   p = plci->internal_req_buffer;
10872   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10873   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10874   w = ch;
10875   *(p++) = (byte) w;
10876   *(p++) = (byte)(w >> 8);
10877   w = ch | XCONNECT_CHANNEL_PORT_PC;
10878   *(p++) = (byte) w;
10879   *(p++) = (byte)(w >> 8);
10880   plci->NData[0].P = plci->internal_req_buffer;
10881   plci->NData[0].PLength = p - plci->internal_req_buffer;
10882   plci->NL.X = plci->NData;
10883   plci->NL.ReqCh = 0;
10884   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10885   plci->adapter->request (&plci->NL);
10886 }
10887
10888
10889 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10890 {
10891
10892   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10893     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10894     (char   *)(FILE_), __LINE__, internal_command));
10895
10896   plci->li_write_command = internal_command;
10897   plci->li_write_channel = 0;
10898 }
10899
10900
10901 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10902 {
10903   DIVA_CAPI_ADAPTER   *a;
10904   word w, n, i, j, r, s, to_ch;
10905   dword d;
10906   byte   *p;
10907   struct xconnect_transfer_address_s   *transfer_address;
10908   byte ch_map[MIXER_CHANNELS_BRI];
10909
10910   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10911     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10912
10913   a = plci->adapter;
10914   if ((plci->li_bchannel_id == 0)
10915    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10916   {
10917     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10918       UnMapId (Id), (char   *)(FILE_), __LINE__));
10919     return (TRUE);
10920   }
10921   i = a->li_base + (plci->li_bchannel_id - 1);
10922   j = plci->li_write_channel;
10923   p = plci->internal_req_buffer;
10924   if (j != 0)
10925   {
10926     if ((Rc != OK) && (Rc != OK_FC))
10927     {
10928       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10929         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10930       return (FALSE);
10931     }
10932   }
10933   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10934   {
10935     r = 0;
10936     s = 0;
10937     if (j < li_total_channels)
10938     {
10939       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10940       {
10941         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10942             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10943           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10944             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10945       }
10946       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10947       while ((j < li_total_channels)
10948         && ((r == 0)
10949          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10950          || (!li_config_table[j].adapter->li_pri
10951           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10952          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10953            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10954           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10955            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10956          || ((li_config_table[j].adapter->li_base != a->li_base)
10957           && !(r & s &
10958             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10959               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10960             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10961               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10962       {
10963         j++;
10964         if (j < li_total_channels)
10965           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10966       }
10967     }
10968     if (j < li_total_channels)
10969     {
10970       plci->internal_command = plci->li_write_command;
10971       if (plci_nl_busy (plci))
10972         return (TRUE);
10973       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10974       *(p++) = UDATA_REQUEST_XCONNECT_TO;
10975       do
10976       {
10977         if (li_config_table[j].adapter->li_base != a->li_base)
10978         {
10979           r &= s &
10980             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10981               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10982             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10983               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10984         }
10985         n = 0;
10986         do
10987         {
10988           if (r & xconnect_write_prog[n].mask)
10989           {
10990             if (xconnect_write_prog[n].from_pc)
10991               transfer_address = &(li_config_table[j].send_pc);
10992             else
10993               transfer_address = &(li_config_table[j].send_b);
10994             d = transfer_address->card_address.low;
10995             *(p++) = (byte) d;
10996             *(p++) = (byte)(d >> 8);
10997             *(p++) = (byte)(d >> 16);
10998             *(p++) = (byte)(d >> 24);
10999             d = transfer_address->card_address.high;
11000             *(p++) = (byte) d;
11001             *(p++) = (byte)(d >> 8);
11002             *(p++) = (byte)(d >> 16);
11003             *(p++) = (byte)(d >> 24);
11004             d = transfer_address->offset;
11005             *(p++) = (byte) d;
11006             *(p++) = (byte)(d >> 8);
11007             *(p++) = (byte)(d >> 16);
11008             *(p++) = (byte)(d >> 24);
11009             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11010             *(p++) = (byte) w;
11011             *(p++) = (byte)(w >> 8);
11012             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11013               (li_config_table[i].adapter->u_law ?
11014                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11015                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11016             *(p++) = (byte) w;
11017             *(p++) = (byte) 0;
11018             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11019           }
11020           n++;
11021         } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11022           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11023         if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11024         {
11025           do
11026           {
11027             j++;
11028             if (j < li_total_channels)
11029               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030           } while ((j < li_total_channels)
11031             && ((r == 0)
11032              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11033              || (!li_config_table[j].adapter->li_pri
11034               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11035              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11036                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11037               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11038                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11039              || ((li_config_table[j].adapter->li_base != a->li_base)
11040               && !(r & s &
11041                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11042                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11043                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11044                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11045         }
11046       } while ((j < li_total_channels)
11047         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11048     }
11049     else if (j == li_total_channels)
11050     {
11051       plci->internal_command = plci->li_write_command;
11052       if (plci_nl_busy (plci))
11053         return (TRUE);
11054       if (a->li_pri)
11055       {
11056         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11057         w = 0;
11058         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11059           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11060         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11061           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11062         *(p++) = (byte) w;
11063         *(p++) = (byte)(w >> 8);
11064       }
11065       else
11066       {
11067         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11068         w = 0;
11069         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11070          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11071         {
11072           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11073         }
11074         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11075           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11076         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11077           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11078         *(p++) = (byte) w;
11079         *(p++) = (byte)(w >> 8);
11080         for (j = 0; j < sizeof(ch_map); j += 2)
11081         {
11082           if (plci->li_bchannel_id == 2)
11083           {
11084             ch_map[j] = (byte)(j+1);
11085             ch_map[j+1] = (byte) j;
11086           }
11087           else
11088           {
11089             ch_map[j] = (byte) j;
11090             ch_map[j+1] = (byte)(j+1);
11091           }
11092         }
11093         for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11094         {
11095           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11096           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11097           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11098           {
11099             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11100               mixer_write_prog_bri[n].xconnect_override :
11101               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11102             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11103             {
11104               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11105               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11106             }
11107           }
11108           else
11109           {
11110             *p = 0x00;
11111             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11112             {
11113               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11114               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11115                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11116             }
11117           }
11118           p++;
11119         }
11120       }
11121       j = li_total_channels + 1;
11122     }
11123   }
11124   else
11125   {
11126     if (j <= li_total_channels)
11127     {
11128       plci->internal_command = plci->li_write_command;
11129       if (plci_nl_busy (plci))
11130         return (TRUE);
11131       if (j < a->li_base)
11132         j = a->li_base;
11133       if (a->li_pri)
11134       {
11135         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11136         w = 0;
11137         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11138           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11139         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11140           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11141         *(p++) = (byte) w;
11142         *(p++) = (byte)(w >> 8);
11143         for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++)
11144         {
11145           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11146           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11147           {
11148             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11149             if (w & mixer_write_prog_pri[n].mask)
11150             {
11151               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11152               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11153             }
11154             else
11155               *(p++) = 0x00;
11156           }
11157           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11158           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11159           {
11160             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11161             if (w & mixer_write_prog_pri[n].mask)
11162             {
11163               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11164               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11165             }
11166             else
11167               *(p++) = 0x00;
11168           }
11169         }
11170       }
11171       else
11172       {
11173         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11174         w = 0;
11175         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11176          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11177         {
11178           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11179         }
11180         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11181           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11182         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11183           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11184         *(p++) = (byte) w;
11185         *(p++) = (byte)(w >> 8);
11186         for (j = 0; j < sizeof(ch_map); j += 2)
11187         {
11188           if (plci->li_bchannel_id == 2)
11189           {
11190             ch_map[j] = (byte)(j+1);
11191             ch_map[j+1] = (byte) j;
11192           }
11193           else
11194           {
11195             ch_map[j] = (byte) j;
11196             ch_map[j+1] = (byte)(j+1);
11197           }
11198         }
11199         for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11200         {
11201           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11202           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11203           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11204           {
11205             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11206             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11207             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11208           }
11209           else
11210           {
11211             *p = 0x00;
11212             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11213             {
11214               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11215               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11216                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11217             }
11218           }
11219           p++;
11220         }
11221       }
11222       j = li_total_channels + 1;
11223     }
11224   }
11225   plci->li_write_channel = j;
11226   if (p != plci->internal_req_buffer)
11227   {
11228     plci->NData[0].P = plci->internal_req_buffer;
11229     plci->NData[0].PLength = p - plci->internal_req_buffer;
11230     plci->NL.X = plci->NData;
11231     plci->NL.ReqCh = 0;
11232     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11233     plci->adapter->request (&plci->NL);
11234   }
11235   return (TRUE);
11236 }
11237
11238
11239 static void mixer_notify_update (PLCI   *plci, byte others)
11240 {
11241   DIVA_CAPI_ADAPTER   *a;
11242   word i, w;
11243   PLCI   *notify_plci;
11244     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11245
11246   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11247     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11248     (char   *)(FILE_), __LINE__, others));
11249
11250   a = plci->adapter;
11251   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11252   {
11253     if (others)
11254       plci->li_notify_update = TRUE;
11255     i = 0;
11256     do
11257     {
11258       notify_plci = NULL;
11259       if (others)
11260       {
11261         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11262           i++;
11263         if (i < li_total_channels)
11264           notify_plci = li_config_table[i++].plci;
11265       }
11266       else
11267       {
11268         if ((plci->li_bchannel_id != 0)
11269          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11270         {
11271           notify_plci = plci;
11272         }
11273       }
11274       if ((notify_plci != NULL)
11275        && !notify_plci->li_notify_update
11276        && (notify_plci->appl != NULL)
11277        && (notify_plci->State)
11278        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11279       {
11280         notify_plci->li_notify_update = TRUE;
11281         ((CAPI_MSG *) msg)->header.length = 18;
11282         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11283         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11284         ((CAPI_MSG *) msg)->header.number = 0;
11285         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11286         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11287         ((CAPI_MSG *) msg)->header.ncci = 0;
11288         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11289         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11290         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11291         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11292         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11293         if (w != _QUEUE_FULL)
11294         {
11295           if (w != 0)
11296           {
11297             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11298               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11299               (char   *)(FILE_), __LINE__,
11300               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11301           }
11302           notify_plci->li_notify_update = FALSE;
11303         }
11304       }
11305     } while (others && (notify_plci != NULL));
11306     if (others)
11307       plci->li_notify_update = FALSE;
11308   }
11309 }
11310
11311
11312 static void mixer_clear_config (PLCI   *plci)
11313 {
11314   DIVA_CAPI_ADAPTER   *a;
11315   word i, j;
11316
11317   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11318     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11319     (char   *)(FILE_), __LINE__));
11320
11321   plci->li_notify_update = FALSE;
11322   plci->li_plci_b_write_pos = 0;
11323   plci->li_plci_b_read_pos = 0;
11324   plci->li_plci_b_req_pos = 0;
11325   a = plci->adapter;
11326   if ((plci->li_bchannel_id != 0)
11327    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11328   {
11329     i = a->li_base + (plci->li_bchannel_id - 1);
11330     li_config_table[i].curchnl = 0;
11331     li_config_table[i].channel = 0;
11332     li_config_table[i].chflags = 0;
11333     for (j = 0; j < li_total_channels; j++)
11334     {
11335       li_config_table[j].flag_table[i] = 0;
11336       li_config_table[i].flag_table[j] = 0;
11337       li_config_table[i].coef_table[j] = 0;
11338       li_config_table[j].coef_table[i] = 0;
11339     }
11340     if (!a->li_pri)
11341     {
11342       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11343       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11344       {
11345         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11346         li_config_table[i].curchnl = 0;
11347         li_config_table[i].channel = 0;
11348         li_config_table[i].chflags = 0;
11349         for (j = 0; j < li_total_channels; j++)
11350         {
11351           li_config_table[i].flag_table[j] = 0;
11352           li_config_table[j].flag_table[i] = 0;
11353           li_config_table[i].coef_table[j] = 0;
11354           li_config_table[j].coef_table[i] = 0;
11355         }
11356         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11357         {
11358           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11359           li_config_table[i].curchnl = 0;
11360           li_config_table[i].channel = 0;
11361           li_config_table[i].chflags = 0;
11362           for (j = 0; j < li_total_channels; j++)
11363           {
11364             li_config_table[i].flag_table[j] = 0;
11365             li_config_table[j].flag_table[i] = 0;
11366             li_config_table[i].coef_table[j] = 0;
11367             li_config_table[j].coef_table[i] = 0;
11368           }
11369         }
11370       }
11371     }
11372   }
11373 }
11374
11375
11376 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11377 {
11378
11379   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11380     UnMapId (Id), (char   *)(FILE_), __LINE__));
11381
11382   do
11383   {
11384     mixer_indication_coefs_set (Id, plci);
11385   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11386 }
11387
11388
11389 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11390 {
11391   DIVA_CAPI_ADAPTER   *a;
11392   word i, j;
11393
11394   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11395     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11396
11397   a = plci->adapter;
11398   if ((plci->li_bchannel_id != 0)
11399    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11400   {
11401     i = a->li_base + (plci->li_bchannel_id - 1);
11402     for (j = 0; j < li_total_channels; j++)
11403     {
11404       li_config_table[i].coef_table[j] &= 0xf;
11405       li_config_table[j].coef_table[i] &= 0xf;
11406     }
11407     if (!a->li_pri)
11408       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11409   }
11410   return (GOOD);
11411 }
11412
11413
11414 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11415 {
11416   DIVA_CAPI_ADAPTER   *a;
11417   word Info;
11418
11419   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11420     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11421
11422   Info = GOOD;
11423   a = plci->adapter;
11424   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11425    && (plci->li_bchannel_id != 0)
11426    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11427   {
11428     switch (plci->adjust_b_state)
11429     {
11430     case ADJUST_B_RESTORE_MIXER_1:
11431       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11432       {
11433         plci->internal_command = plci->adjust_b_command;
11434         if (plci_nl_busy (plci))
11435         {
11436           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11437           break;
11438         }
11439         xconnect_query_addresses (plci);
11440         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11441         break;
11442       }
11443       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11444       Rc = OK;
11445     case ADJUST_B_RESTORE_MIXER_2:
11446     case ADJUST_B_RESTORE_MIXER_3:
11447     case ADJUST_B_RESTORE_MIXER_4:
11448       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11449       {
11450         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11451           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11452         Info = _WRONG_STATE;
11453         break;
11454       }
11455       if (Rc == OK)
11456       {
11457         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11458           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11459         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11460           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11461       }
11462       else if (Rc == 0)
11463       {
11464         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11465           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11466         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11467           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11468       }
11469       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11470       {
11471         plci->internal_command = plci->adjust_b_command;
11472         break;
11473       }
11474     case ADJUST_B_RESTORE_MIXER_5:
11475       xconnect_write_coefs (plci, plci->adjust_b_command);
11476       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11477       Rc = OK;
11478     case ADJUST_B_RESTORE_MIXER_6:
11479       if (!xconnect_write_coefs_process (Id, plci, Rc))
11480       {
11481         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11482           UnMapId (Id), (char   *)(FILE_), __LINE__));
11483         Info = _FACILITY_NOT_SUPPORTED;
11484         break;
11485       }
11486       if (plci->internal_command)
11487         break;
11488       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11489     case ADJUST_B_RESTORE_MIXER_7:
11490       break;
11491     }
11492   }
11493   return (Info);
11494 }
11495
11496
11497 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11498 {
11499   DIVA_CAPI_ADAPTER   *a;
11500   word i, internal_command, Info;
11501
11502   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11503     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11504     plci->li_cmd));
11505
11506   Info = GOOD;
11507   a = plci->adapter;
11508   internal_command = plci->internal_command;
11509   plci->internal_command = 0;
11510   switch (plci->li_cmd)
11511   {
11512   case LI_REQ_CONNECT:
11513   case LI_REQ_DISCONNECT:
11514   case LI_REQ_SILENT_UPDATE:
11515     switch (internal_command)
11516     {
11517     default:
11518       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11519       {
11520         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11521           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11522       }
11523     case MIXER_COMMAND_1:
11524       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11525       {
11526         if (adjust_b_process (Id, plci, Rc) != GOOD)
11527         {
11528           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11529             UnMapId (Id), (char   *)(FILE_), __LINE__));
11530           Info = _FACILITY_NOT_SUPPORTED;
11531           break;
11532         }
11533         if (plci->internal_command)
11534           return;
11535       }
11536       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11537       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11538        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11539         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11540          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11541       {
11542         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11543       }
11544       else
11545       {
11546         do
11547         {
11548           mixer_indication_coefs_set (Id, plci);
11549         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11550       }
11551     case MIXER_COMMAND_2:
11552       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11553        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11554         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11555          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556       {
11557         if (!xconnect_write_coefs_process (Id, plci, Rc))
11558         {
11559           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11560             UnMapId (Id), (char   *)(FILE_), __LINE__));
11561           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11562           {
11563             do
11564             {
11565               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11566                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11567               i = (plci->li_plci_b_write_pos == 0) ?
11568                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11569             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11570               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11571           }
11572           Info = _FACILITY_NOT_SUPPORTED;
11573           break;
11574         }
11575         if (plci->internal_command)
11576           return;
11577       }
11578       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11579       {
11580         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11581           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11582       }
11583     case MIXER_COMMAND_3:
11584       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11585       {
11586         if (adjust_b_process (Id, plci, Rc) != GOOD)
11587         {
11588           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11589             UnMapId (Id), (char   *)(FILE_), __LINE__));
11590           Info = _FACILITY_NOT_SUPPORTED;
11591           break;
11592         }
11593         if (plci->internal_command)
11594           return;
11595       }
11596       break;
11597     }
11598     break;
11599   }
11600   if ((plci->li_bchannel_id == 0)
11601    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11602   {
11603     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11604       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11605   }
11606   else
11607   {
11608     i = a->li_base + (plci->li_bchannel_id - 1);
11609     li_config_table[i].curchnl = plci->li_channel_bits;
11610     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11611     {
11612       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11613       li_config_table[i].curchnl = plci->li_channel_bits;
11614       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11615       {
11616         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11617         li_config_table[i].curchnl = plci->li_channel_bits;
11618       }
11619     }
11620   }
11621 }
11622
11623
11624 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11625   dword plci_b_id, byte connect, dword li_flags)
11626 {
11627   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11628   PLCI   *plci_b;
11629   DIVA_CAPI_ADAPTER   *a_b;
11630
11631   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11632   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11633   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11634   if (!a->li_pri && (plci->tel == ADV_VOICE)
11635    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11636   {
11637     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11638     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11639       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11640   }
11641   else
11642   {
11643     ch_a_v = ch_a;
11644     ch_a_s = ch_a;
11645   }
11646   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11647   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11648    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11649   {
11650     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11651     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11652       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11653   }
11654   else
11655   {
11656     ch_b_v = ch_b;
11657     ch_b_s = ch_b;
11658   }
11659   if (connect)
11660   {
11661     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11662     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11663     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11664     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11665   }
11666   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11667   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11668   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670   if (ch_a_v == ch_b_v)
11671   {
11672     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11673     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11674   }
11675   else
11676   {
11677     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11678     {
11679       for (i = 0; i < li_total_channels; i++)
11680       {
11681         if (i != ch_a_v)
11682           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11683       }
11684     }
11685     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11686     {
11687       for (i = 0; i < li_total_channels; i++)
11688       {
11689         if (i != ch_a_s)
11690           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11691       }
11692     }
11693     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11694     {
11695       for (i = 0; i < li_total_channels; i++)
11696       {
11697         if (i != ch_a_v)
11698           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11699       }
11700     }
11701     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11702     {
11703       for (i = 0; i < li_total_channels; i++)
11704       {
11705         if (i != ch_a_s)
11706           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11707       }
11708     }
11709   }
11710   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11711   {
11712     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11713     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11714     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11715     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11716   }
11717   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11718   {
11719     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11720     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11721     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11722     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11723   }
11724   if (li_flags & LI_FLAG_MONITOR_A)
11725   {
11726     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11727     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11728   }
11729   if (li_flags & LI_FLAG_MONITOR_B)
11730   {
11731     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11732     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11733   }
11734   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11735   {
11736     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11737     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11738   }
11739   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11740   {
11741     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11742     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743   }
11744   if (li_flags & LI_FLAG_MIX_A)
11745   {
11746     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11747     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11748   }
11749   if (li_flags & LI_FLAG_MIX_B)
11750   {
11751     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11752     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11753   }
11754   if (ch_a_v != ch_a_s)
11755   {
11756     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11757     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11758   }
11759   if (ch_b_v != ch_b_s)
11760   {
11761     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11762     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11763   }
11764 }
11765
11766
11767 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11768   dword plci_b_id, byte connect, dword li_flags)
11769 {
11770   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11771   PLCI   *plci_b;
11772   DIVA_CAPI_ADAPTER   *a_b;
11773
11774   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11775   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11776   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11777   if (!a->li_pri && (plci->tel == ADV_VOICE)
11778    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11779   {
11780     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11781     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11782       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11783   }
11784   else
11785   {
11786     ch_a_v = ch_a;
11787     ch_a_s = ch_a;
11788   }
11789   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11790   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11791    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11792   {
11793     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11794     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11795       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11796   }
11797   else
11798   {
11799     ch_b_v = ch_b;
11800     ch_b_s = ch_b;
11801   }
11802   if (connect)
11803   {
11804     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11805     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11806     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11807     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11808     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11809     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11810   }
11811   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11820   {
11821     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11822     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11823     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11824     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11825   }
11826   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11827   {
11828     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11829     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11830     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11831     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11832   }
11833   if (li_flags & LI2_FLAG_MONITOR_B)
11834   {
11835     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11836     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11837   }
11838   if (li_flags & LI2_FLAG_MIX_B)
11839   {
11840     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11841     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11842   }
11843   if (li_flags & LI2_FLAG_MONITOR_X)
11844     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11845   if (li_flags & LI2_FLAG_MIX_X)
11846     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11847   if (li_flags & LI2_FLAG_LOOP_B)
11848   {
11849     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11850     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11851     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11852     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11853   }
11854   if (li_flags & LI2_FLAG_LOOP_PC)
11855     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11856   if (li_flags & LI2_FLAG_LOOP_X)
11857     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11858   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11859     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11860   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11861     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11862   if (ch_a_v != ch_a_s)
11863   {
11864     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11865     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11866   }
11867   if (ch_b_v != ch_b_s)
11868   {
11869     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11870     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11871   }
11872 }
11873
11874
11875 static word li_check_main_plci (dword Id, PLCI   *plci)
11876 {
11877   if (plci == NULL)
11878   {
11879     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11880       UnMapId (Id), (char   *)(FILE_), __LINE__));
11881     return (_WRONG_IDENTIFIER);
11882   }
11883   if (!plci->State
11884    || !plci->NL.Id || plci->nl_remove_id
11885    || (plci->li_bchannel_id == 0))
11886   {
11887     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11888       UnMapId (Id), (char   *)(FILE_), __LINE__));
11889     return (_WRONG_STATE);
11890   }
11891   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11892   return (GOOD);
11893 }
11894
11895
11896 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11897   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11898 {
11899   byte ctlr_b;
11900   PLCI   *plci_b;
11901
11902   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11903     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11904   {
11905     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11906       UnMapId (Id), (char   *)(FILE_), __LINE__));
11907     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11908     return (NULL);
11909   }
11910   ctlr_b = 0;
11911   if ((plci_b_id & 0x7f) != 0)
11912   {
11913     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11914     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11915       ctlr_b = 0;
11916   }
11917   if ((ctlr_b == 0)
11918    || (((plci_b_id >> 8) & 0xff) == 0)
11919    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11920   {
11921     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11922       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11923     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11924     return (NULL);
11925   }
11926   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11927   if (!plci_b->State
11928    || !plci_b->NL.Id || plci_b->nl_remove_id
11929    || (plci_b->li_bchannel_id == 0))
11930   {
11931     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11932       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11933     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11934     return (NULL);
11935   }
11936   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11937   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11938     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11939    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11940     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11941   {
11942     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11943       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11944     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11945     return (NULL);
11946   }
11947   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11948     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11949   {
11950     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11951       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11952     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11953     return (NULL);
11954   }
11955   return (plci_b);
11956 }
11957
11958
11959 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11960   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11961 {
11962   byte ctlr_b;
11963   PLCI   *plci_b;
11964
11965   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11966     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11967   {
11968     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11969       UnMapId (Id), (char   *)(FILE_), __LINE__));
11970     PUT_WORD (p_result, _WRONG_STATE);
11971     return (NULL);
11972   }
11973   ctlr_b = 0;
11974   if ((plci_b_id & 0x7f) != 0)
11975   {
11976     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11977     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11978       ctlr_b = 0;
11979   }
11980   if ((ctlr_b == 0)
11981    || (((plci_b_id >> 8) & 0xff) == 0)
11982    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11983   {
11984     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11985       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11986     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11987     return (NULL);
11988   }
11989   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11990   if (!plci_b->State
11991    || !plci_b->NL.Id || plci_b->nl_remove_id
11992    || (plci_b->li_bchannel_id == 0)
11993    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11994   {
11995     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11996       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11997     PUT_WORD (p_result, _WRONG_STATE);
11998     return (NULL);
11999   }
12000   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12001     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12002    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12003     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12004   {
12005     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12006       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12007     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12008     return (NULL);
12009   }
12010   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12011     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12012   {
12013     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12014       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12015     PUT_WORD (p_result, _WRONG_STATE);
12016     return (NULL);
12017   }
12018   return (plci_b);
12019 }
12020
12021
12022 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12023 {
12024   word Info;
12025   word i;
12026   dword d, li_flags, plci_b_id;
12027   PLCI   *plci_b;
12028     API_PARSE li_parms[3];
12029     API_PARSE li_req_parms[3];
12030     API_PARSE li_participant_struct[2];
12031     API_PARSE li_participant_parms[3];
12032   word participant_parms_pos;
12033   byte result_buffer[32];
12034   byte   *result;
12035   word result_pos;
12036   word plci_b_write_pos;
12037
12038   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12039     UnMapId (Id), (char   *)(FILE_), __LINE__));
12040
12041   Info = GOOD;
12042   result = result_buffer;
12043   result_buffer[0] = 0;
12044   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12045   {
12046     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12047       UnMapId (Id), (char   *)(FILE_), __LINE__));
12048     Info = _FACILITY_NOT_SUPPORTED;
12049   }
12050   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12051   {
12052     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12053       UnMapId (Id), (char   *)(FILE_), __LINE__));
12054     Info = _WRONG_MESSAGE_FORMAT;
12055   }
12056   else
12057   {
12058     result_buffer[0] = 3;
12059     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12060     result_buffer[3] = 0;
12061     switch (GET_WORD (li_parms[0].info))
12062     {
12063     case LI_GET_SUPPORTED_SERVICES:
12064       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12065       {
12066         result_buffer[0] = 17;
12067         result_buffer[3] = 14;
12068         PUT_WORD (&result_buffer[4], GOOD);
12069         d = 0;
12070         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12071           d |= LI_CONFERENCING_SUPPORTED;
12072         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12073           d |= LI_MONITORING_SUPPORTED;
12074         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12075           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12076         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12077           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12078         PUT_DWORD (&result_buffer[6], d);
12079         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12080         {
12081           d = 0;
12082           for (i = 0; i < li_total_channels; i++)
12083           {
12084             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12085              && (li_config_table[i].adapter->li_pri
12086               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12087             {
12088               d++;
12089             }
12090           }
12091         }
12092         else
12093         {
12094           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12095         }
12096         PUT_DWORD (&result_buffer[10], d / 2);
12097         PUT_DWORD (&result_buffer[14], d);
12098       }
12099       else
12100       {
12101         result_buffer[0] = 25;
12102         result_buffer[3] = 22;
12103         PUT_WORD (&result_buffer[4], GOOD);
12104         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12105         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12106           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12107         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12108           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12109         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12110           d |= LI2_PC_LOOPING_SUPPORTED;
12111         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12112           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12113         PUT_DWORD (&result_buffer[6], d);
12114         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12115         PUT_DWORD (&result_buffer[10], d / 2);
12116         PUT_DWORD (&result_buffer[14], d - 1);
12117         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118         {
12119           d = 0;
12120           for (i = 0; i < li_total_channels; i++)
12121           {
12122             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12123              && (li_config_table[i].adapter->li_pri
12124               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12125             {
12126               d++;
12127             }
12128           }
12129         }
12130         PUT_DWORD (&result_buffer[18], d / 2);
12131         PUT_DWORD (&result_buffer[22], d - 1);
12132       }
12133       break;
12134
12135     case LI_REQ_CONNECT:
12136       if (li_parms[1].length == 8)
12137       {
12138         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12139         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12140         {
12141           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12142             UnMapId (Id), (char   *)(FILE_), __LINE__));
12143           Info = _WRONG_MESSAGE_FORMAT;
12144           break;
12145         }
12146         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12147         li_flags = GET_DWORD (li_req_parms[1].info);
12148         Info = li_check_main_plci (Id, plci);
12149         result_buffer[0] = 9;
12150         result_buffer[3] = 6;
12151         PUT_DWORD (&result_buffer[4], plci_b_id);
12152         PUT_WORD (&result_buffer[8], GOOD);
12153         if (Info != GOOD)
12154           break;
12155         result = plci->saved_msg.info;
12156         for (i = 0; i <= result_buffer[0]; i++)
12157           result[i] = result_buffer[i];
12158         plci_b_write_pos = plci->li_plci_b_write_pos;
12159         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12160         if (plci_b == NULL)
12161           break;
12162         li_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12163         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12164         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12165         plci->li_plci_b_write_pos = plci_b_write_pos;
12166       }
12167       else
12168       {
12169         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12170         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12171         {
12172           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12173             UnMapId (Id), (char   *)(FILE_), __LINE__));
12174           Info = _WRONG_MESSAGE_FORMAT;
12175           break;
12176         }
12177         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12178         Info = li_check_main_plci (Id, plci);
12179         result_buffer[0] = 7;
12180         result_buffer[3] = 4;
12181         PUT_WORD (&result_buffer[4], Info);
12182         result_buffer[6] = 0;
12183         if (Info != GOOD)
12184           break;
12185         result = plci->saved_msg.info;
12186         for (i = 0; i <= result_buffer[0]; i++)
12187           result[i] = result_buffer[i];
12188         plci_b_write_pos = plci->li_plci_b_write_pos;
12189         participant_parms_pos = 0;
12190         result_pos = 7;
12191         li2_update_connect (Id, a, plci, UnMapId (Id), TRUE, li_flags);
12192         while (participant_parms_pos < li_req_parms[1].length)
12193         {
12194           result[result_pos] = 6;
12195           result_pos += 7;
12196           PUT_DWORD (&result[result_pos - 6], 0);
12197           PUT_WORD (&result[result_pos - 2], GOOD);
12198           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12199             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12200           {
12201             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12202               UnMapId (Id), (char   *)(FILE_), __LINE__));
12203             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12204             break;
12205           }
12206           if (api_parse (&li_participant_struct[0].info[1],
12207             li_participant_struct[0].length, "dd", li_participant_parms))
12208           {
12209             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12210               UnMapId (Id), (char   *)(FILE_), __LINE__));
12211             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12212             break;
12213           }
12214           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12215           li_flags = GET_DWORD (li_participant_parms[1].info);
12216           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12217           if (sizeof(result) - result_pos < 7)
12218           {
12219             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12220               UnMapId (Id), (char   *)(FILE_), __LINE__));
12221             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12222             break;
12223           }
12224           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12225           if (plci_b != NULL)
12226           {
12227             li2_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12228             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12229               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12230               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12231             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12232           }
12233           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12234             (&li_req_parms[1].info[1]));
12235         }
12236         result[0] = (byte)(result_pos - 1);
12237         result[3] = (byte)(result_pos - 4);
12238         result[6] = (byte)(result_pos - 7);
12239         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12240         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12241          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12242         {
12243           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12244           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12245         }
12246         else
12247           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12248         plci->li_plci_b_write_pos = plci_b_write_pos;
12249       }
12250       mixer_calculate_coefs (a);
12251       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12252       mixer_notify_update (plci, TRUE);
12253       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12254         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12255       plci->command = 0;
12256       plci->li_cmd = GET_WORD (li_parms[0].info);
12257       start_internal_command (Id, plci, mixer_command);
12258       return (FALSE);
12259
12260     case LI_REQ_DISCONNECT:
12261       if (li_parms[1].length == 4)
12262       {
12263         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12264         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12265         {
12266           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12267             UnMapId (Id), (char   *)(FILE_), __LINE__));
12268           Info = _WRONG_MESSAGE_FORMAT;
12269           break;
12270         }
12271         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12272         Info = li_check_main_plci (Id, plci);
12273         result_buffer[0] = 9;
12274         result_buffer[3] = 6;
12275         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12276         PUT_WORD (&result_buffer[8], GOOD);
12277         if (Info != GOOD)
12278           break;
12279         result = plci->saved_msg.info;
12280         for (i = 0; i <= result_buffer[0]; i++)
12281           result[i] = result_buffer[i];
12282         plci_b_write_pos = plci->li_plci_b_write_pos;
12283         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12284         if (plci_b == NULL)
12285           break;
12286         li_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12287         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12288         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12289         plci->li_plci_b_write_pos = plci_b_write_pos;
12290       }
12291       else
12292       {
12293         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12294         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12295         {
12296           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12297             UnMapId (Id), (char   *)(FILE_), __LINE__));
12298           Info = _WRONG_MESSAGE_FORMAT;
12299           break;
12300         }
12301         Info = li_check_main_plci (Id, plci);
12302         result_buffer[0] = 7;
12303         result_buffer[3] = 4;
12304         PUT_WORD (&result_buffer[4], Info);
12305         result_buffer[6] = 0;
12306         if (Info != GOOD)
12307           break;
12308         result = plci->saved_msg.info;
12309         for (i = 0; i <= result_buffer[0]; i++)
12310           result[i] = result_buffer[i];
12311         plci_b_write_pos = plci->li_plci_b_write_pos;
12312         participant_parms_pos = 0;
12313         result_pos = 7;
12314         while (participant_parms_pos < li_req_parms[0].length)
12315         {
12316           result[result_pos] = 6;
12317           result_pos += 7;
12318           PUT_DWORD (&result[result_pos - 6], 0);
12319           PUT_WORD (&result[result_pos - 2], GOOD);
12320           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12321             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12322           {
12323             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12324               UnMapId (Id), (char   *)(FILE_), __LINE__));
12325             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12326             break;
12327           }
12328           if (api_parse (&li_participant_struct[0].info[1],
12329             li_participant_struct[0].length, "d", li_participant_parms))
12330           {
12331             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12332               UnMapId (Id), (char   *)(FILE_), __LINE__));
12333             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12334             break;
12335           }
12336           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12337           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12338           if (sizeof(result) - result_pos < 7)
12339           {
12340             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12341               UnMapId (Id), (char   *)(FILE_), __LINE__));
12342             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12343             break;
12344           }
12345           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12346           if (plci_b != NULL)
12347           {
12348             li2_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12349             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12350             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12351           }
12352           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12353             (&li_req_parms[0].info[1]));
12354         }
12355         result[0] = (byte)(result_pos - 1);
12356         result[3] = (byte)(result_pos - 4);
12357         result[6] = (byte)(result_pos - 7);
12358         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12359         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12360          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12361         {
12362           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12363           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12364         }
12365         else
12366           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12367         plci->li_plci_b_write_pos = plci_b_write_pos;
12368       }
12369       mixer_calculate_coefs (a);
12370       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12371       mixer_notify_update (plci, TRUE);
12372       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12373         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12374       plci->command = 0;
12375       plci->li_cmd = GET_WORD (li_parms[0].info);
12376       start_internal_command (Id, plci, mixer_command);
12377       return (FALSE);
12378
12379     case LI_REQ_SILENT_UPDATE:
12380       if (!plci || !plci->State
12381        || !plci->NL.Id || plci->nl_remove_id
12382        || (plci->li_bchannel_id == 0)
12383        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12384       {
12385         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12386           UnMapId (Id), (char   *)(FILE_), __LINE__));
12387         return (FALSE);
12388       }
12389       plci_b_write_pos = plci->li_plci_b_write_pos;
12390       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12391         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12392       {
12393         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12394           UnMapId (Id), (char   *)(FILE_), __LINE__));
12395         return (FALSE);
12396       }
12397       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12398       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12399        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12400       {
12401         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12402         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12403       }
12404       else
12405         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12406       plci->li_plci_b_write_pos = plci_b_write_pos;
12407       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12408       plci->command = 0;
12409       plci->li_cmd = GET_WORD (li_parms[0].info);
12410       start_internal_command (Id, plci, mixer_command);
12411       return (FALSE);
12412
12413     default:
12414       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12415         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12416       Info = _FACILITY_NOT_SUPPORTED;
12417     }
12418   }
12419   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12420     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12421   return (FALSE);
12422 }
12423
12424
12425 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12426 {
12427   dword d;
12428   DIVA_CAPI_ADAPTER   *a;
12429     byte result[12];
12430
12431   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12432     UnMapId (Id), (char   *)(FILE_), __LINE__));
12433
12434   a = plci->adapter;
12435   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12436   {
12437     do
12438     {
12439       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12440       if (!(d & LI_PLCI_B_SKIP_FLAG))
12441       {
12442         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12443         {
12444           if (d & LI_PLCI_B_DISC_FLAG)
12445           {
12446             result[0] = 5;
12447             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12448             result[3] = 2;
12449             PUT_WORD (&result[4], _LI_USER_INITIATED);
12450           }
12451           else
12452           {
12453             result[0] = 7;
12454             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12455             result[3] = 4;
12456             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12457           }
12458         }
12459         else
12460         {
12461           if (d & LI_PLCI_B_DISC_FLAG)
12462           {
12463             result[0] = 9;
12464             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12465             result[3] = 6;
12466             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12467             PUT_WORD (&result[8], _LI_USER_INITIATED);
12468           }
12469           else
12470           {
12471             result[0] = 7;
12472             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12473             result[3] = 4;
12474             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12475           }
12476         }
12477         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12478           "ws", SELECTOR_LINE_INTERCONNECT, result);
12479       }
12480       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12481         0 : plci->li_plci_b_read_pos + 1;
12482     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12483   }
12484 }
12485
12486
12487 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12488 {
12489   word i, j, ch;
12490   struct xconnect_transfer_address_s s,   *p;
12491   DIVA_CAPI_ADAPTER   *a;
12492
12493   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12494     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12495
12496   a = plci->adapter;
12497   i = 1;
12498   for (i = 1; i < length; i += 16)
12499   {
12500     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12501     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12502     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12503     ch = msg[i+12] | (msg[i+13] << 8);
12504     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12505     if (!a->li_pri && (plci->li_bchannel_id == 2))
12506       j = 1 - j;
12507     j += a->li_base;
12508     if (ch & XCONNECT_CHANNEL_PORT_PC)
12509       p = &(li_config_table[j].send_pc);
12510     else
12511       p = &(li_config_table[j].send_b);
12512     p->card_address.low = s.card_address.low;
12513     p->card_address.high = s.card_address.high;
12514     p->offset = s.offset;
12515     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12516   }
12517   if (plci->internal_command_queue[0]
12518    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12519     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12520     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12521   {
12522     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12523     if (!plci->internal_command)
12524       next_internal_command (Id, plci);
12525   }
12526   mixer_notify_update (plci, TRUE);
12527 }
12528
12529
12530 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12531 {
12532
12533   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12534     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12535
12536 }
12537
12538
12539 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12540 {
12541   word plci_b_write_pos;
12542
12543   plci_b_write_pos = plci->li_plci_b_write_pos;
12544   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12545     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12546   {
12547     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12548       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12549       (char   *)(FILE_), __LINE__));
12550     return (FALSE);
12551   }
12552   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12553   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12554   plci->li_plci_b_write_pos = plci_b_write_pos;
12555   return (TRUE);
12556 }
12557
12558
12559 static void mixer_remove (PLCI   *plci)
12560 {
12561   DIVA_CAPI_ADAPTER   *a;
12562   PLCI   *notify_plci;
12563   dword plci_b_id;
12564   word i, j;
12565
12566   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12567     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12568     (char   *)(FILE_), __LINE__));
12569
12570   a = plci->adapter;
12571   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12572   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12573   {
12574     if ((plci->li_bchannel_id != 0)
12575      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12576     {
12577       i = a->li_base + (plci->li_bchannel_id - 1);
12578       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12579       {
12580         for (j = 0; j < li_total_channels; j++)
12581         {
12582           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12583            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12584           {
12585             notify_plci = li_config_table[j].plci;
12586             if ((notify_plci != NULL)
12587              && (notify_plci != plci)
12588              && (notify_plci->appl != NULL)
12589              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12590              && (notify_plci->State)
12591              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12592             {
12593               mixer_notify_source_removed (notify_plci, plci_b_id);
12594             }
12595           }
12596         }
12597         mixer_clear_config (plci);
12598         mixer_calculate_coefs (a);
12599         mixer_notify_update (plci, TRUE);
12600       }
12601       li_config_table[i].plci = NULL;
12602       plci->li_bchannel_id = 0;
12603     }
12604   }
12605 }
12606
12607
12608 /*------------------------------------------------------------------*/
12609 /* Echo canceller facilities                                        */
12610 /*------------------------------------------------------------------*/
12611
12612
12613 static void ec_write_parameters (PLCI   *plci)
12614 {
12615   word w;
12616     byte parameter_buffer[6];
12617
12618   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12619     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12620     (char   *)(FILE_), __LINE__));
12621
12622   parameter_buffer[0] = 5;
12623   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12624   PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12625   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12626   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12627   PUT_WORD (&parameter_buffer[4], w);
12628   add_p (plci, FTY, parameter_buffer);
12629   sig_req (plci, TEL_CTRL, 0);
12630   send_req (plci);
12631 }
12632
12633
12634 static void ec_clear_config (PLCI   *plci)
12635 {
12636
12637   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12638     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12639     (char   *)(FILE_), __LINE__));
12640
12641   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12642     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12643   plci->ec_tail_length = 0;
12644 }
12645
12646
12647 static void ec_prepare_switch (dword Id, PLCI   *plci)
12648 {
12649
12650   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12651     UnMapId (Id), (char   *)(FILE_), __LINE__));
12652
12653 }
12654
12655
12656 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12657 {
12658
12659   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12660     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12661
12662   return (GOOD);
12663 }
12664
12665
12666 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12667 {
12668   word Info;
12669
12670   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12671     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672
12673   Info = GOOD;
12674   if (plci->B1_facilities & B1_FACILITY_EC)
12675   {
12676     switch (plci->adjust_b_state)
12677     {
12678     case ADJUST_B_RESTORE_EC_1:
12679       plci->internal_command = plci->adjust_b_command;
12680       if (plci->sig_req)
12681       {
12682         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12683         break;
12684       }
12685       ec_write_parameters (plci);
12686       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12687       break;
12688     case ADJUST_B_RESTORE_EC_2:
12689       if ((Rc != OK) && (Rc != OK_FC))
12690       {
12691         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12692           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12693         Info = _WRONG_STATE;
12694         break;
12695       }
12696       break;
12697     }
12698   }
12699   return (Info);
12700 }
12701
12702
12703 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12704 {
12705   word internal_command, Info;
12706     byte result[8];
12707
12708   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12709     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12710     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12711
12712   Info = GOOD;
12713   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12714   {
12715     result[0] = 2;
12716     PUT_WORD (&result[1], EC_SUCCESS);
12717   }
12718   else
12719   {
12720     result[0] = 5;
12721     PUT_WORD (&result[1], plci->ec_cmd);
12722     result[3] = 2;
12723     PUT_WORD (&result[4], GOOD);
12724   }
12725   internal_command = plci->internal_command;
12726   plci->internal_command = 0;
12727   switch (plci->ec_cmd)
12728   {
12729   case EC_ENABLE_OPERATION:
12730   case EC_FREEZE_COEFFICIENTS:
12731   case EC_RESUME_COEFFICIENT_UPDATE:
12732   case EC_RESET_COEFFICIENTS:
12733     switch (internal_command)
12734     {
12735     default:
12736       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12737         B1_FACILITY_EC), EC_COMMAND_1);
12738     case EC_COMMAND_1:
12739       if (adjust_b_process (Id, plci, Rc) != GOOD)
12740       {
12741         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12742           UnMapId (Id), (char   *)(FILE_), __LINE__));
12743         Info = _FACILITY_NOT_SUPPORTED;
12744         break;
12745       }
12746       if (plci->internal_command)
12747         return;
12748     case EC_COMMAND_2:
12749       if (plci->sig_req)
12750       {
12751         plci->internal_command = EC_COMMAND_2;
12752         return;
12753       }
12754       plci->internal_command = EC_COMMAND_3;
12755       ec_write_parameters (plci);
12756       return;
12757     case EC_COMMAND_3:
12758       if ((Rc != OK) && (Rc != OK_FC))
12759       {
12760         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12761           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12762         Info = _FACILITY_NOT_SUPPORTED;
12763         break;
12764       }
12765       break;
12766     }
12767     break;
12768
12769   case EC_DISABLE_OPERATION:
12770     switch (internal_command)
12771     {
12772     default:
12773     case EC_COMMAND_1:
12774       if (plci->B1_facilities & B1_FACILITY_EC)
12775       {
12776         if (plci->sig_req)
12777         {
12778           plci->internal_command = EC_COMMAND_1;
12779           return;
12780         }
12781         plci->internal_command = EC_COMMAND_2;
12782         ec_write_parameters (plci);
12783         return;
12784       }
12785       Rc = OK;
12786     case EC_COMMAND_2:
12787       if ((Rc != OK) && (Rc != OK_FC))
12788       {
12789         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12790           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12791         Info = _FACILITY_NOT_SUPPORTED;
12792         break;
12793       }
12794       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12795         ~B1_FACILITY_EC), EC_COMMAND_3);
12796     case EC_COMMAND_3:
12797       if (adjust_b_process (Id, plci, Rc) != GOOD)
12798       {
12799         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12800           UnMapId (Id), (char   *)(FILE_), __LINE__));
12801         Info = _FACILITY_NOT_SUPPORTED;
12802         break;
12803       }
12804       if (plci->internal_command)
12805         return;
12806       break;
12807     }
12808     break;
12809   }
12810   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12811     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12812     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12813 }
12814
12815
12816 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12817 {
12818   word Info;
12819   word opt;
12820     API_PARSE ec_parms[3];
12821     byte result[16];
12822
12823   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12824     UnMapId (Id), (char   *)(FILE_), __LINE__));
12825
12826   Info = GOOD;
12827   result[0] = 0;
12828   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12829   {
12830     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12831       UnMapId (Id), (char   *)(FILE_), __LINE__));
12832     Info = _FACILITY_NOT_SUPPORTED;
12833   }
12834   else
12835   {
12836     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12837     {
12838       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12839       {
12840         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12841           UnMapId (Id), (char   *)(FILE_), __LINE__));
12842         Info = _WRONG_MESSAGE_FORMAT;
12843       }
12844       else
12845       {
12846         if (plci == NULL)
12847         {
12848           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12849             UnMapId (Id), (char   *)(FILE_), __LINE__));
12850           Info = _WRONG_IDENTIFIER;
12851         }
12852         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12853         {
12854           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12855             UnMapId (Id), (char   *)(FILE_), __LINE__));
12856           Info = _WRONG_STATE;
12857         }
12858         else
12859         {
12860           plci->command = 0;
12861           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12862           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12863           result[0] = 2;
12864           PUT_WORD (&result[1], EC_SUCCESS);
12865           if (msg[1].length >= 4)
12866           {
12867             opt = GET_WORD (&ec_parms[0].info[2]);
12868             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12869               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12870             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12871               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12872             if (opt & EC_DETECT_DISABLE_TONE)
12873               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12874             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12875               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12876             if (msg[1].length >= 6)
12877             {
12878               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12879             }
12880           }
12881           switch (plci->ec_cmd)
12882           {
12883           case EC_ENABLE_OPERATION:
12884             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12885             start_internal_command (Id, plci, ec_command);
12886             return (FALSE);
12887
12888           case EC_DISABLE_OPERATION:
12889             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12890               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12891               LEC_RESET_COEFFICIENTS;
12892             start_internal_command (Id, plci, ec_command);
12893             return (FALSE);
12894
12895           case EC_FREEZE_COEFFICIENTS:
12896             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12897             start_internal_command (Id, plci, ec_command);
12898             return (FALSE);
12899
12900           case EC_RESUME_COEFFICIENT_UPDATE:
12901             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12902             start_internal_command (Id, plci, ec_command);
12903             return (FALSE);
12904
12905           case EC_RESET_COEFFICIENTS:
12906             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12907             start_internal_command (Id, plci, ec_command);
12908             return (FALSE);
12909
12910           default:
12911             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12912               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12913             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12914           }
12915         }
12916       }
12917     }
12918     else
12919     {
12920       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12921       {
12922         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12923           UnMapId (Id), (char   *)(FILE_), __LINE__));
12924         Info = _WRONG_MESSAGE_FORMAT;
12925       }
12926       else
12927       {
12928         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12929         {
12930           result[0] = 11;
12931           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12932           result[3] = 8;
12933           PUT_WORD (&result[4], GOOD);
12934           PUT_WORD (&result[6], 0x0007);
12935           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12936           PUT_WORD (&result[10], 0);
12937         }
12938         else if (plci == NULL)
12939         {
12940           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12941             UnMapId (Id), (char   *)(FILE_), __LINE__));
12942           Info = _WRONG_IDENTIFIER;
12943         }
12944         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12945         {
12946           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12947             UnMapId (Id), (char   *)(FILE_), __LINE__));
12948           Info = _WRONG_STATE;
12949         }
12950         else
12951         {
12952           plci->command = 0;
12953           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12954           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12955           result[0] = 5;
12956           PUT_WORD (&result[1], plci->ec_cmd);
12957           result[3] = 2;
12958           PUT_WORD (&result[4], GOOD);
12959           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12960             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12961           plci->ec_tail_length = 0;
12962           if (ec_parms[1].length >= 2)
12963           {
12964             opt = GET_WORD (&ec_parms[1].info[1]);
12965             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12966               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12967             if (opt & EC_DETECT_DISABLE_TONE)
12968               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12969             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12970               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12971             if (ec_parms[1].length >= 4)
12972             {
12973               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12974             }
12975           }
12976           switch (plci->ec_cmd)
12977           {
12978           case EC_ENABLE_OPERATION:
12979             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12980             start_internal_command (Id, plci, ec_command);
12981             return (FALSE);
12982
12983           case EC_DISABLE_OPERATION:
12984             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12985               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12986               LEC_RESET_COEFFICIENTS;
12987             start_internal_command (Id, plci, ec_command);
12988             return (FALSE);
12989
12990           default:
12991             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12992               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12993             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12994           }
12995         }
12996       }
12997     }
12998   }
12999   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13000     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13001     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13002   return (FALSE);
13003 }
13004
13005
13006 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13007 {
13008     byte result[8];
13009
13010   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13011     UnMapId (Id), (char   *)(FILE_), __LINE__));
13012
13013   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13014   {
13015     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13016     {
13017       result[0] = 2;
13018       PUT_WORD (&result[1], 0);
13019       switch (msg[1])
13020       {
13021       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13022         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13023         break;
13024       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13025         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13026         break;
13027       case LEC_DISABLE_RELEASED:
13028         PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13029         break;
13030       }
13031     }
13032     else
13033     {
13034       result[0] = 5;
13035       PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13036       result[3] = 2;
13037       PUT_WORD (&result[4], 0);
13038       switch (msg[1])
13039       {
13040       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13041         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13042         break;
13043       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13044         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13045         break;
13046       case LEC_DISABLE_RELEASED:
13047         PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13048         break;
13049       }
13050     }
13051     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13052       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13053   }
13054 }
13055
13056
13057
13058 /*------------------------------------------------------------------*/
13059 /* Advanced voice                                                   */
13060 /*------------------------------------------------------------------*/
13061
13062 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13063 {
13064   DIVA_CAPI_ADAPTER   *a;
13065   word i;
13066   byte *p;
13067
13068   word w, n, j, k;
13069   byte ch_map[MIXER_CHANNELS_BRI];
13070
13071     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13072
13073   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13074     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13075     (char   *)(FILE_), __LINE__, write_command));
13076
13077   a = plci->adapter;
13078   p = coef_buffer + 1;
13079   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13080   i = 0;
13081   while (i + sizeof(word) <= a->adv_voice_coef_length)
13082   {
13083     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13084     p += 2;
13085     i += 2;
13086   }
13087   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13088   {
13089     PUT_WORD (p, 0x8000);
13090     p += 2;
13091     i += 2;
13092   }
13093
13094   if (!a->li_pri && (plci->li_bchannel_id == 0))
13095   {
13096     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13097     {
13098       plci->li_bchannel_id = 1;
13099       li_config_table[a->li_base].plci = plci;
13100       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13101         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13102         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13103     }
13104     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13105     {
13106       plci->li_bchannel_id = 2;
13107       li_config_table[a->li_base + 1].plci = plci;
13108       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13109         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13110         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13111     }
13112   }
13113   if (!a->li_pri && (plci->li_bchannel_id != 0)
13114    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13115   {
13116     i = a->li_base + (plci->li_bchannel_id - 1);
13117     switch (write_command)
13118     {
13119     case ADV_VOICE_WRITE_ACTIVATION:
13120       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13121       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13122       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13123       {
13124         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13125         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13126       }
13127       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13128       {
13129         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13130         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13131         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13132         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13133       }
13134       mixer_calculate_coefs (a);
13135       li_config_table[i].curchnl = li_config_table[i].channel;
13136       li_config_table[j].curchnl = li_config_table[j].channel;
13137       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13138         li_config_table[k].curchnl = li_config_table[k].channel;
13139       break;
13140
13141     case ADV_VOICE_WRITE_DEACTIVATION:
13142       for (j = 0; j < li_total_channels; j++)
13143       {
13144         li_config_table[i].flag_table[j] = 0;
13145         li_config_table[j].flag_table[i] = 0;
13146       }
13147       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13148       for (j = 0; j < li_total_channels; j++)
13149       {
13150         li_config_table[k].flag_table[j] = 0;
13151         li_config_table[j].flag_table[k] = 0;
13152       }
13153       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13154       {
13155         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13156         for (j = 0; j < li_total_channels; j++)
13157         {
13158           li_config_table[k].flag_table[j] = 0;
13159           li_config_table[j].flag_table[k] = 0;
13160         }
13161       }
13162       mixer_calculate_coefs (a);
13163       break;
13164     }
13165     if (plci->B1_facilities & B1_FACILITY_MIXER)
13166     {
13167       w = 0;
13168       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13169         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13170       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13171         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13172       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13173         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13174       *(p++) = (byte) w;
13175       *(p++) = (byte)(w >> 8);
13176       for (j = 0; j < sizeof(ch_map); j += 2)
13177       {
13178         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13179         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13180       }
13181       for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
13182       {
13183         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13184         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13185         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13186         {
13187           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13188           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13189           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13190         }
13191         else
13192         {
13193           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13194             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13195         }
13196       }
13197     }
13198     else
13199     {
13200       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13201         *(p++) = a->adv_voice_coef_buffer[i];
13202     }
13203   }
13204   else
13205
13206   {
13207     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13208       *(p++) = a->adv_voice_coef_buffer[i];
13209   }
13210   coef_buffer[0] = (p - coef_buffer) - 1;
13211   add_p (plci, FTY, coef_buffer);
13212   sig_req (plci, TEL_CTRL, 0);
13213   send_req (plci);
13214 }
13215
13216
13217 static void adv_voice_clear_config (PLCI   *plci)
13218 {
13219   DIVA_CAPI_ADAPTER   *a;
13220
13221   word i, j;
13222
13223
13224   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13225     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13226     (char   *)(FILE_), __LINE__));
13227
13228   a = plci->adapter;
13229   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13230   {
13231     a->adv_voice_coef_length = 0;
13232
13233     if (!a->li_pri && (plci->li_bchannel_id != 0)
13234      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13235     {
13236       i = a->li_base + (plci->li_bchannel_id - 1);
13237       li_config_table[i].curchnl = 0;
13238       li_config_table[i].channel = 0;
13239       li_config_table[i].chflags = 0;
13240       for (j = 0; j < li_total_channels; j++)
13241       {
13242         li_config_table[i].flag_table[j] = 0;
13243         li_config_table[j].flag_table[i] = 0;
13244         li_config_table[i].coef_table[j] = 0;
13245         li_config_table[j].coef_table[i] = 0;
13246       }
13247       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13248       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13249       li_config_table[i].curchnl = 0;
13250       li_config_table[i].channel = 0;
13251       li_config_table[i].chflags = 0;
13252       for (j = 0; j < li_total_channels; j++)
13253       {
13254         li_config_table[i].flag_table[j] = 0;
13255         li_config_table[j].flag_table[i] = 0;
13256         li_config_table[i].coef_table[j] = 0;
13257         li_config_table[j].coef_table[i] = 0;
13258       }
13259       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13260       {
13261         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13262         li_config_table[i].curchnl = 0;
13263         li_config_table[i].channel = 0;
13264         li_config_table[i].chflags = 0;
13265         for (j = 0; j < li_total_channels; j++)
13266         {
13267           li_config_table[i].flag_table[j] = 0;
13268           li_config_table[j].flag_table[i] = 0;
13269           li_config_table[i].coef_table[j] = 0;
13270           li_config_table[j].coef_table[i] = 0;
13271         }
13272       }
13273     }
13274
13275   }
13276 }
13277
13278
13279 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13280 {
13281
13282   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13283     UnMapId (Id), (char   *)(FILE_), __LINE__));
13284
13285 }
13286
13287
13288 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13289 {
13290
13291   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13292     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13293
13294   return (GOOD);
13295 }
13296
13297
13298 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13299 {
13300   DIVA_CAPI_ADAPTER   *a;
13301   word Info;
13302
13303   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13304     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13305
13306   Info = GOOD;
13307   a = plci->adapter;
13308   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13309    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13310   {
13311     switch (plci->adjust_b_state)
13312     {
13313     case ADJUST_B_RESTORE_VOICE_1:
13314       plci->internal_command = plci->adjust_b_command;
13315       if (plci->sig_req)
13316       {
13317         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13318         break;
13319       }
13320       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13321       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13322       break;
13323     case ADJUST_B_RESTORE_VOICE_2:
13324       if ((Rc != OK) && (Rc != OK_FC))
13325       {
13326         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13327           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13328         Info = _WRONG_STATE;
13329         break;
13330       }
13331       break;
13332     }
13333   }
13334   return (Info);
13335 }
13336
13337
13338
13339
13340 /*------------------------------------------------------------------*/
13341 /* B1 resource switching                                            */
13342 /*------------------------------------------------------------------*/
13343
13344 static byte b1_facilities_table[] =
13345 {
13346   0x00,  /* 0  No bchannel resources      */
13347   0x00,  /* 1  Codec (automatic law)      */
13348   0x00,  /* 2  Codec (A-law)              */
13349   0x00,  /* 3  Codec (y-law)              */
13350   0x00,  /* 4  HDLC for X.21              */
13351   0x00,  /* 5  HDLC                       */
13352   0x00,  /* 6  External Device 0          */
13353   0x00,  /* 7  External Device 1          */
13354   0x00,  /* 8  HDLC 56k                   */
13355   0x00,  /* 9  Transparent                */
13356   0x00,  /* 10 Loopback to network        */
13357   0x00,  /* 11 Test pattern to net        */
13358   0x00,  /* 12 Rate adaptation sync       */
13359   0x00,  /* 13 Rate adaptation async      */
13360   0x00,  /* 14 R-Interface                */
13361   0x00,  /* 15 HDLC 128k leased line      */
13362   0x00,  /* 16 FAX                        */
13363   0x00,  /* 17 Modem async                */
13364   0x00,  /* 18 Modem sync HDLC            */
13365   0x00,  /* 19 V.110 async HDLC           */
13366   0x12,  /* 20 Adv voice (Trans,mixer)    */
13367   0x00,  /* 21 Codec connected to IC      */
13368   0x0c,  /* 22 Trans,DTMF                 */
13369   0x1e,  /* 23 Trans,DTMF+mixer           */
13370   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13371   0x13,  /* 25 Trans,mixer+local          */
13372   0x12,  /* 26 HDLC,mixer                 */
13373   0x12,  /* 27 HDLC 56k,mixer             */
13374   0x2c,  /* 28 Trans,LEC+DTMF             */
13375   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13376   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13377   0x2c,  /* 31 RTP,LEC+DTMF               */
13378   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13379   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13380   0x00,  /* 34 Signaling task             */
13381   0x00,  /* 35 PIAFS                      */
13382   0x0c,  /* 36 Trans,DTMF+TONE            */
13383   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13384   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13385 };
13386
13387
13388 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13389 {
13390   word b1_facilities;
13391
13392   b1_facilities = b1_facilities_table[b1_resource];
13393   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13394   {
13395
13396     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13397        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13398
13399     {
13400       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13401         b1_facilities |= B1_FACILITY_DTMFX;
13402       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13403         b1_facilities |= B1_FACILITY_DTMFR;
13404     }
13405   }
13406   if ((b1_resource == 17) || (b1_resource == 18))
13407   {
13408     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13409       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13410   }
13411 /*
13412   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13413     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13414     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13415 */
13416   return (b1_facilities);
13417 }
13418
13419
13420 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13421 {
13422   byte b;
13423
13424   switch (b1_resource)
13425   {
13426   case 5:
13427   case 26:
13428     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13429       b = 26;
13430     else
13431       b = 5;
13432     break;
13433
13434   case 8:
13435   case 27:
13436     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13437       b = 27;
13438     else
13439       b = 8;
13440     break;
13441
13442   case 9:
13443   case 20:
13444   case 22:
13445   case 23:
13446   case 24:
13447   case 25:
13448   case 28:
13449   case 29:
13450   case 30:
13451   case 36:
13452   case 37:
13453   case 38:
13454     if (b1_facilities & B1_FACILITY_EC)
13455     {
13456       if (b1_facilities & B1_FACILITY_LOCAL)
13457         b = 30;
13458       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13459         b = 29;
13460       else
13461         b = 28;
13462     }
13463
13464     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13465       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13466        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13467     {
13468       if (b1_facilities & B1_FACILITY_LOCAL)
13469         b = 38;
13470       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13471         b = 37;
13472       else
13473         b = 36;
13474     }
13475
13476     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13477       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13478      || ((b1_facilities & B1_FACILITY_DTMFR)
13479       && ((b1_facilities & B1_FACILITY_MIXER)
13480        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13481      || ((b1_facilities & B1_FACILITY_DTMFX)
13482       && ((b1_facilities & B1_FACILITY_MIXER)
13483        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13484     {
13485       if (b1_facilities & B1_FACILITY_LOCAL)
13486         b = 24;
13487       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13488         b = 23;
13489       else
13490         b = 22;
13491     }
13492     else
13493     {
13494       if (b1_facilities & B1_FACILITY_LOCAL)
13495         b = 25;
13496       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13497         b = 20;
13498       else
13499         b = 9;
13500     }
13501     break;
13502
13503   case 31:
13504   case 32:
13505   case 33:
13506     if (b1_facilities & B1_FACILITY_LOCAL)
13507       b = 33;
13508     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13509       b = 32;
13510     else
13511       b = 31;
13512     break;
13513
13514   default:
13515     b = b1_resource;
13516   }
13517   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13518     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13519     (char   *)(FILE_), __LINE__,
13520     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13521   return (b);
13522 }
13523
13524
13525 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13526 {
13527   word removed_facilities;
13528
13529   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13530     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13531     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13532     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13533
13534   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13535   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13536
13537   if (removed_facilities & B1_FACILITY_EC)
13538     ec_clear_config (plci);
13539
13540
13541   if (removed_facilities & B1_FACILITY_DTMFR)
13542   {
13543     dtmf_rec_clear_config (plci);
13544     dtmf_parameter_clear_config (plci);
13545   }
13546   if (removed_facilities & B1_FACILITY_DTMFX)
13547     dtmf_send_clear_config (plci);
13548
13549
13550   if (removed_facilities & B1_FACILITY_MIXER)
13551     mixer_clear_config (plci);
13552
13553   if (removed_facilities & B1_FACILITY_VOICE)
13554     adv_voice_clear_config (plci);
13555   plci->B1_facilities = new_b1_facilities;
13556 }
13557
13558
13559 static void adjust_b_clear (PLCI   *plci)
13560 {
13561
13562   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13563     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13564     (char   *)(FILE_), __LINE__));
13565
13566   plci->adjust_b_restore = FALSE;
13567 }
13568
13569
13570 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13571 {
13572   word Info;
13573   byte b1_resource;
13574   NCCI   * ncci_ptr;
13575     API_PARSE bp[2];
13576
13577   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13578     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13579
13580   Info = GOOD;
13581   switch (plci->adjust_b_state)
13582   {
13583   case ADJUST_B_START:
13584     if ((plci->adjust_b_parms_msg == NULL)
13585      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13586      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13587       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13588     {
13589       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13590         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13591       if (b1_resource == plci->B1_resource)
13592       {
13593         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13594         break;
13595       }
13596       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13597       {
13598         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13599           UnMapId (Id), (char   *)(FILE_), __LINE__,
13600           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13601         Info = _WRONG_STATE;
13602         break;
13603       }
13604     }
13605     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13606     {
13607
13608       mixer_prepare_switch (Id, plci);
13609
13610
13611       dtmf_prepare_switch (Id, plci);
13612       dtmf_parameter_prepare_switch (Id, plci);
13613
13614
13615       ec_prepare_switch (Id, plci);
13616
13617       adv_voice_prepare_switch (Id, plci);
13618     }
13619     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13620     Rc = OK;
13621   case ADJUST_B_SAVE_MIXER_1:
13622     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13623     {
13624
13625       Info = mixer_save_config (Id, plci, Rc);
13626       if ((Info != GOOD) || plci->internal_command)
13627         break;
13628
13629     }
13630     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13631     Rc = OK;
13632   case ADJUST_B_SAVE_DTMF_1:
13633     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634     {
13635
13636       Info = dtmf_save_config (Id, plci, Rc);
13637       if ((Info != GOOD) || plci->internal_command)
13638         break;
13639
13640     }
13641     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13642   case ADJUST_B_REMOVE_L23_1:
13643     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13644      && plci->NL.Id && !plci->nl_remove_id)
13645     {
13646       plci->internal_command = plci->adjust_b_command;
13647       if (plci->adjust_b_ncci != 0)
13648       {
13649         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13650         while (ncci_ptr->data_pending)
13651         {
13652           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13653           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13654         }
13655         while (ncci_ptr->data_ack_pending)
13656           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13657       }
13658       nl_req_ncci (plci, REMOVE,
13659         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13660       send_req (plci);
13661       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13662       break;
13663     }
13664     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13665     Rc = OK;
13666   case ADJUST_B_REMOVE_L23_2:
13667     if ((Rc != OK) && (Rc != OK_FC))
13668     {
13669       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13670         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13671       Info = _WRONG_STATE;
13672       break;
13673     }
13674     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13675     {
13676       if (plci_nl_busy (plci))
13677       {
13678         plci->internal_command = plci->adjust_b_command;
13679         break;
13680       }
13681     }
13682     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13683     Rc = OK;
13684   case ADJUST_B_SAVE_EC_1:
13685     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13686     {
13687
13688       Info = ec_save_config (Id, plci, Rc);
13689       if ((Info != GOOD) || plci->internal_command)
13690         break;
13691
13692     }
13693     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13694     Rc = OK;
13695   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13696     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13697     {
13698
13699       Info = dtmf_parameter_save_config (Id, plci, Rc);
13700       if ((Info != GOOD) || plci->internal_command)
13701         break;
13702
13703     }
13704     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13705     Rc = OK;
13706   case ADJUST_B_SAVE_VOICE_1:
13707     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708     {
13709       Info = adv_voice_save_config (Id, plci, Rc);
13710       if ((Info != GOOD) || plci->internal_command)
13711         break;
13712     }
13713     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13714   case ADJUST_B_SWITCH_L1_1:
13715     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13716     {
13717       if (plci->sig_req)
13718       {
13719         plci->internal_command = plci->adjust_b_command;
13720         break;
13721       }
13722       if (plci->adjust_b_parms_msg != NULL)
13723         api_load_msg (plci->adjust_b_parms_msg, bp);
13724       else
13725         api_load_msg (&plci->B_protocol, bp);
13726       Info = add_b1 (plci, bp,
13727         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13728         plci->adjust_b_facilities);
13729       if (Info != GOOD)
13730       {
13731         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13732           UnMapId (Id), (char   *)(FILE_), __LINE__,
13733           plci->B1_resource, plci->adjust_b_facilities));
13734         break;
13735       }
13736       plci->internal_command = plci->adjust_b_command;
13737       sig_req (plci, RESOURCES, 0);
13738       send_req (plci);
13739       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13740       break;
13741     }
13742     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13743     Rc = OK;
13744   case ADJUST_B_SWITCH_L1_2:
13745     if ((Rc != OK) && (Rc != OK_FC))
13746     {
13747       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13748         UnMapId (Id), (char   *)(FILE_), __LINE__,
13749         Rc, plci->B1_resource, plci->adjust_b_facilities));
13750       Info = _WRONG_STATE;
13751       break;
13752     }
13753     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13754     Rc = OK;
13755   case ADJUST_B_RESTORE_VOICE_1:
13756   case ADJUST_B_RESTORE_VOICE_2:
13757     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13758     {
13759       Info = adv_voice_restore_config (Id, plci, Rc);
13760       if ((Info != GOOD) || plci->internal_command)
13761         break;
13762     }
13763     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13764     Rc = OK;
13765   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13766   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13767     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13768     {
13769
13770       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13771       if ((Info != GOOD) || plci->internal_command)
13772         break;
13773
13774     }
13775     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13776     Rc = OK;
13777   case ADJUST_B_RESTORE_EC_1:
13778   case ADJUST_B_RESTORE_EC_2:
13779     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13780     {
13781
13782       Info = ec_restore_config (Id, plci, Rc);
13783       if ((Info != GOOD) || plci->internal_command)
13784         break;
13785
13786     }
13787     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13788   case ADJUST_B_ASSIGN_L23_1:
13789     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13790     {
13791       if (plci_nl_busy (plci))
13792       {
13793         plci->internal_command = plci->adjust_b_command;
13794         break;
13795       }
13796       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13797         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13798       if (plci->adjust_b_parms_msg != NULL)
13799         api_load_msg (plci->adjust_b_parms_msg, bp);
13800       else
13801         api_load_msg (&plci->B_protocol, bp);
13802       Info = add_b23 (plci, bp);
13803       if (Info != GOOD)
13804       {
13805         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13806           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13807         break;
13808       }
13809       plci->internal_command = plci->adjust_b_command;
13810       nl_req_ncci (plci, ASSIGN, 0);
13811       send_req (plci);
13812       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13813       break;
13814     }
13815     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13816     Rc = ASSIGN_OK;
13817   case ADJUST_B_ASSIGN_L23_2:
13818     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13819     {
13820       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13821         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13822       Info = _WRONG_STATE;
13823       break;
13824     }
13825     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13826     {
13827       if (Rc != ASSIGN_OK)
13828       {
13829         plci->internal_command = plci->adjust_b_command;
13830         break;
13831       }
13832     }
13833     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13834     {
13835       plci->adjust_b_restore = TRUE;
13836       break;
13837     }
13838     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13839   case ADJUST_B_CONNECT_1:
13840     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13841     {
13842       plci->internal_command = plci->adjust_b_command;
13843       if (plci_nl_busy (plci))
13844         break;
13845       nl_req_ncci (plci, N_CONNECT, 0);
13846       send_req (plci);
13847       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13848       break;
13849     }
13850     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13851     Rc = OK;
13852   case ADJUST_B_CONNECT_2:
13853   case ADJUST_B_CONNECT_3:
13854   case ADJUST_B_CONNECT_4:
13855     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13856     {
13857       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13858         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13859       Info = _WRONG_STATE;
13860       break;
13861     }
13862     if (Rc == OK)
13863     {
13864       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13865       {
13866         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13867         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13868       }
13869       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13870         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13871       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13872         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13873     }
13874     else if (Rc == 0)
13875     {
13876       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13877         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13878       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13879         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13880     }
13881     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13882     {
13883       plci->internal_command = plci->adjust_b_command;
13884       break;
13885     }
13886     Rc = OK;
13887   case ADJUST_B_RESTORE_DTMF_1:
13888   case ADJUST_B_RESTORE_DTMF_2:
13889     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13890     {
13891
13892       Info = dtmf_restore_config (Id, plci, Rc);
13893       if ((Info != GOOD) || plci->internal_command)
13894         break;
13895
13896     }
13897     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13898     Rc = OK;
13899   case ADJUST_B_RESTORE_MIXER_1:
13900   case ADJUST_B_RESTORE_MIXER_2:
13901   case ADJUST_B_RESTORE_MIXER_3:
13902   case ADJUST_B_RESTORE_MIXER_4:
13903   case ADJUST_B_RESTORE_MIXER_5:
13904   case ADJUST_B_RESTORE_MIXER_6:
13905   case ADJUST_B_RESTORE_MIXER_7:
13906     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13907     {
13908
13909       Info = mixer_restore_config (Id, plci, Rc);
13910       if ((Info != GOOD) || plci->internal_command)
13911         break;
13912
13913     }
13914     plci->adjust_b_state = ADJUST_B_END;
13915   case ADJUST_B_END:
13916     break;
13917   }
13918   return (Info);
13919 }
13920
13921
13922 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13923 {
13924
13925   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13926     UnMapId (Id), (char   *)(FILE_), __LINE__,
13927     plci->B1_resource, b1_facilities));
13928
13929   plci->adjust_b_parms_msg = bp_msg;
13930   plci->adjust_b_facilities = b1_facilities;
13931   plci->adjust_b_command = internal_command;
13932   plci->adjust_b_ncci = (word)(Id >> 16);
13933   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13934     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13935   else
13936     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13937   plci->adjust_b_state = ADJUST_B_START;
13938   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13939     UnMapId (Id), (char   *)(FILE_), __LINE__,
13940     plci->B1_resource, b1_facilities));
13941 }
13942
13943
13944 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13945 {
13946   word internal_command;
13947
13948   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13949     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13950
13951   internal_command = plci->internal_command;
13952   plci->internal_command = 0;
13953   switch (internal_command)
13954   {
13955   default:
13956     plci->command = 0;
13957     if (plci->req_in != 0)
13958     {
13959       plci->internal_command = ADJUST_B_RESTORE_1;
13960       break;
13961     }
13962     Rc = OK;
13963   case ADJUST_B_RESTORE_1:
13964     if ((Rc != OK) && (Rc != OK_FC))
13965     {
13966       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13967         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13968     }
13969     plci->adjust_b_parms_msg = NULL;
13970     plci->adjust_b_facilities = plci->B1_facilities;
13971     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13972     plci->adjust_b_ncci = (word)(Id >> 16);
13973     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13974     plci->adjust_b_state = ADJUST_B_START;
13975     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13976       UnMapId (Id), (char   *)(FILE_), __LINE__));
13977   case ADJUST_B_RESTORE_2:
13978     if (adjust_b_process (Id, plci, Rc) != GOOD)
13979     {
13980       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13981         UnMapId (Id), (char   *)(FILE_), __LINE__));
13982     }
13983     if (plci->internal_command)
13984       break;
13985     break;
13986   }
13987 }
13988
13989
13990 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
13991 {
13992   word Info;
13993   word internal_command;
13994
13995   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13996     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13997
13998   Info = GOOD;
13999   internal_command = plci->internal_command;
14000   plci->internal_command = 0;
14001   switch (internal_command)
14002   {
14003   default:
14004     plci->command = 0;
14005     plci->adjust_b_parms_msg = NULL;
14006     plci->adjust_b_facilities = plci->B1_facilities;
14007     plci->adjust_b_command = RESET_B3_COMMAND_1;
14008     plci->adjust_b_ncci = (word)(Id >> 16);
14009     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14010     plci->adjust_b_state = ADJUST_B_START;
14011     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14012       UnMapId (Id), (char   *)(FILE_), __LINE__));
14013   case RESET_B3_COMMAND_1:
14014     Info = adjust_b_process (Id, plci, Rc);
14015     if (Info != GOOD)
14016     {
14017       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14018         UnMapId (Id), (char   *)(FILE_), __LINE__));
14019       break;
14020     }
14021     if (plci->internal_command)
14022       return;
14023     break;
14024   }
14025 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14026   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14027 }
14028
14029
14030 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14031 {
14032   word Info;
14033   word internal_command;
14034   byte esc_chi[3];
14035
14036   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14037     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14038
14039   Info = GOOD;
14040   internal_command = plci->internal_command;
14041   plci->internal_command = 0;
14042   switch (internal_command)
14043   {
14044   default:
14045     plci->command = 0;
14046     plci->adjust_b_parms_msg = &plci->saved_msg;
14047     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14048       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14049     else
14050       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14051     plci->adjust_b_command = SELECT_B_COMMAND_1;
14052     plci->adjust_b_ncci = (word)(Id >> 16);
14053     if (plci->saved_msg.parms[0].length == 0)
14054     {
14055       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14056         ADJUST_B_MODE_NO_RESOURCE;
14057     }
14058     else
14059     {
14060       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14061         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14062     }
14063     plci->adjust_b_state = ADJUST_B_START;
14064     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14065       UnMapId (Id), (char   *)(FILE_), __LINE__));
14066   case SELECT_B_COMMAND_1:
14067     Info = adjust_b_process (Id, plci, Rc);
14068     if (Info != GOOD)
14069     {
14070       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14071         UnMapId (Id), (char   *)(FILE_), __LINE__));
14072       break;
14073     }
14074     if (plci->internal_command)
14075       return;
14076     if (plci->tel == ADV_VOICE)
14077     {
14078       esc_chi[0] = 0x02;
14079       esc_chi[1] = 0x18;
14080       esc_chi[2] = plci->b_channel;
14081       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14082     }
14083     break;
14084   }
14085   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14086 }
14087
14088
14089 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14090 {
14091   word Info;
14092   word internal_command;
14093
14094   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14095     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14096
14097   Info = GOOD;
14098   internal_command = plci->internal_command;
14099   plci->internal_command = 0;
14100   switch (internal_command)
14101   {
14102   default:
14103     plci->command = 0;
14104   case FAX_CONNECT_ACK_COMMAND_1:
14105     if (plci_nl_busy (plci))
14106     {
14107       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14108       return;
14109     }
14110     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14111     plci->NData[0].P = plci->fax_connect_info_buffer;
14112     plci->NData[0].PLength = plci->fax_connect_info_length;
14113     plci->NL.X = plci->NData;
14114     plci->NL.ReqCh = 0;
14115     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14116     plci->adapter->request (&plci->NL);
14117     return;
14118   case FAX_CONNECT_ACK_COMMAND_2:
14119     if ((Rc != OK) && (Rc != OK_FC))
14120     {
14121       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14122         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14123       break;
14124     }
14125   }
14126   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14127    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14128   {
14129     if (plci->B3_prot == 4)
14130       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14131     else
14132       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14133     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14134   }
14135 }
14136
14137
14138 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14139 {
14140   word Info;
14141   word internal_command;
14142
14143   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14144     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14145
14146   Info = GOOD;
14147   internal_command = plci->internal_command;
14148   plci->internal_command = 0;
14149   switch (internal_command)
14150   {
14151   default:
14152     plci->command = 0;
14153   case FAX_EDATA_ACK_COMMAND_1:
14154     if (plci_nl_busy (plci))
14155     {
14156       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14157       return;
14158     }
14159     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14160     plci->NData[0].P = plci->fax_connect_info_buffer;
14161     plci->NData[0].PLength = plci->fax_edata_ack_length;
14162     plci->NL.X = plci->NData;
14163     plci->NL.ReqCh = 0;
14164     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14165     plci->adapter->request (&plci->NL);
14166     return;
14167   case FAX_EDATA_ACK_COMMAND_2:
14168     if ((Rc != OK) && (Rc != OK_FC))
14169     {
14170       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14171         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14172       break;
14173     }
14174   }
14175 }
14176
14177
14178 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14179 {
14180   word Info;
14181   word internal_command;
14182
14183   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14184     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14185
14186   Info = GOOD;
14187   internal_command = plci->internal_command;
14188   plci->internal_command = 0;
14189   switch (internal_command)
14190   {
14191   default:
14192     plci->command = 0;
14193   case FAX_CONNECT_INFO_COMMAND_1:
14194     if (plci_nl_busy (plci))
14195     {
14196       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14197       return;
14198     }
14199     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14200     plci->NData[0].P = plci->fax_connect_info_buffer;
14201     plci->NData[0].PLength = plci->fax_connect_info_length;
14202     plci->NL.X = plci->NData;
14203     plci->NL.ReqCh = 0;
14204     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14205     plci->adapter->request (&plci->NL);
14206     return;
14207   case FAX_CONNECT_INFO_COMMAND_2:
14208     if ((Rc != OK) && (Rc != OK_FC))
14209     {
14210       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14211         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14212       Info = _WRONG_STATE;
14213       break;
14214     }
14215     if (plci_nl_busy (plci))
14216     {
14217       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14218       return;
14219     }
14220     plci->command = _CONNECT_B3_R;
14221     nl_req_ncci (plci, N_CONNECT, 0);
14222     send_req (plci);
14223     return;
14224   }
14225   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14226 }
14227
14228
14229 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14230 {
14231   word Info;
14232   word internal_command;
14233
14234   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14235     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14236
14237   Info = GOOD;
14238   internal_command = plci->internal_command;
14239   plci->internal_command = 0;
14240   switch (internal_command)
14241   {
14242   default:
14243     plci->command = 0;
14244     plci->adjust_b_parms_msg = NULL;
14245     plci->adjust_b_facilities = plci->B1_facilities;
14246     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14247     plci->adjust_b_ncci = (word)(Id >> 16);
14248     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14249     plci->adjust_b_state = ADJUST_B_START;
14250     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14251       UnMapId (Id), (char   *)(FILE_), __LINE__));
14252   case FAX_ADJUST_B23_COMMAND_1:
14253     Info = adjust_b_process (Id, plci, Rc);
14254     if (Info != GOOD)
14255     {
14256       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14257         UnMapId (Id), (char   *)(FILE_), __LINE__));
14258       break;
14259     }
14260     if (plci->internal_command)
14261       return;
14262   case FAX_ADJUST_B23_COMMAND_2:
14263     if (plci_nl_busy (plci))
14264     {
14265       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14266       return;
14267     }
14268     plci->command = _CONNECT_B3_R;
14269     nl_req_ncci (plci, N_CONNECT, 0);
14270     send_req (plci);
14271     return;
14272   }
14273   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14274 }
14275
14276
14277 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14278 {
14279   word internal_command;
14280
14281   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14282     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14283
14284   internal_command = plci->internal_command;
14285   plci->internal_command = 0;
14286   switch (internal_command)
14287   {
14288   default:
14289     plci->command = 0;
14290     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14291     return;
14292   case FAX_DISCONNECT_COMMAND_1:
14293   case FAX_DISCONNECT_COMMAND_2:
14294   case FAX_DISCONNECT_COMMAND_3:
14295     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14296     {
14297       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14298         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14299       break;
14300     }
14301     if (Rc == OK)
14302     {
14303       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14304        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14305       {
14306         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14307       }
14308     }
14309     else if (Rc == 0)
14310     {
14311       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14312         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14313     }
14314     return;
14315   }
14316 }
14317
14318
14319
14320 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14321 {
14322   word Info;
14323   word internal_command;
14324
14325   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14326     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14327
14328   Info = GOOD;
14329   internal_command = plci->internal_command;
14330   plci->internal_command = 0;
14331   switch (internal_command)
14332   {
14333   default:
14334     plci->command = 0;
14335   case RTP_CONNECT_B3_REQ_COMMAND_1:
14336     if (plci_nl_busy (plci))
14337     {
14338       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14339       return;
14340     }
14341     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14342     nl_req_ncci (plci, N_CONNECT, 0);
14343     send_req (plci);
14344     return;
14345   case RTP_CONNECT_B3_REQ_COMMAND_2:
14346     if ((Rc != OK) && (Rc != OK_FC))
14347     {
14348       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14349         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14350       Info = _WRONG_STATE;
14351       break;
14352     }
14353     if (plci_nl_busy (plci))
14354     {
14355       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14356       return;
14357     }
14358     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14359     plci->NData[0].PLength = plci->internal_req_buffer[0];
14360     plci->NData[0].P = plci->internal_req_buffer + 1;
14361     plci->NL.X = plci->NData;
14362     plci->NL.ReqCh = 0;
14363     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14364     plci->adapter->request (&plci->NL);
14365     break;
14366   case RTP_CONNECT_B3_REQ_COMMAND_3:
14367     return;
14368   }
14369   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14370 }
14371
14372
14373 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14374 {
14375   word Info;
14376   word internal_command;
14377
14378   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14379     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14380
14381   Info = GOOD;
14382   internal_command = plci->internal_command;
14383   plci->internal_command = 0;
14384   switch (internal_command)
14385   {
14386   default:
14387     plci->command = 0;
14388   case RTP_CONNECT_B3_RES_COMMAND_1:
14389     if (plci_nl_busy (plci))
14390     {
14391       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14392       return;
14393     }
14394     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14395     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14396     send_req (plci);
14397     return;
14398   case RTP_CONNECT_B3_RES_COMMAND_2:
14399     if ((Rc != OK) && (Rc != OK_FC))
14400     {
14401       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14402         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14403       Info = _WRONG_STATE;
14404       break;
14405     }
14406     if (plci_nl_busy (plci))
14407     {
14408       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14409       return;
14410     }
14411     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14412     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14413     plci->NData[0].PLength = plci->internal_req_buffer[0];
14414     plci->NData[0].P = plci->internal_req_buffer + 1;
14415     plci->NL.X = plci->NData;
14416     plci->NL.ReqCh = 0;
14417     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14418     plci->adapter->request (&plci->NL);
14419     return;
14420   case RTP_CONNECT_B3_RES_COMMAND_3:
14421     return;
14422   }
14423 }
14424
14425
14426
14427 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14428 {
14429     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14430   word Info;
14431   word internal_command;
14432
14433   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14434     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14435
14436   Info = GOOD;
14437   internal_command = plci->internal_command;
14438   plci->internal_command = 0;
14439   switch (internal_command)
14440   {
14441   default:
14442     if (!plci->NL.Id)
14443       break;
14444     plci->command = 0;
14445     plci->adjust_b_parms_msg = NULL;
14446     plci->adjust_b_facilities = plci->B1_facilities;
14447     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14448     plci->adjust_b_ncci = (word)(Id >> 16);
14449     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14450     plci->adjust_b_state = ADJUST_B_START;
14451     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14452       UnMapId (Id), (char   *)(FILE_), __LINE__));
14453   case HOLD_SAVE_COMMAND_1:
14454     Info = adjust_b_process (Id, plci, Rc);
14455     if (Info != GOOD)
14456     {
14457       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14458         UnMapId (Id), (char   *)(FILE_), __LINE__));
14459       break;
14460     }
14461     if (plci->internal_command)
14462       return;
14463   }
14464   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14465 }
14466
14467
14468 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14469 {
14470     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14471   word Info;
14472   word internal_command;
14473
14474   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14475     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14476
14477   Info = GOOD;
14478   internal_command = plci->internal_command;
14479   plci->internal_command = 0;
14480   switch (internal_command)
14481   {
14482   default:
14483     plci->command = 0;
14484     plci->adjust_b_parms_msg = NULL;
14485     plci->adjust_b_facilities = plci->B1_facilities;
14486     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14487     plci->adjust_b_ncci = (word)(Id >> 16);
14488     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14489     plci->adjust_b_state = ADJUST_B_START;
14490     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14491       UnMapId (Id), (char   *)(FILE_), __LINE__));
14492   case RETRIEVE_RESTORE_COMMAND_1:
14493     Info = adjust_b_process (Id, plci, Rc);
14494     if (Info != GOOD)
14495     {
14496       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14497         UnMapId (Id), (char   *)(FILE_), __LINE__));
14498       break;
14499     }
14500     if (plci->internal_command)
14501       return;
14502   }
14503   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14504 }
14505
14506
14507 static void init_b1_config (PLCI   *plci)
14508 {
14509
14510   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14511     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14512     (char   *)(FILE_), __LINE__));
14513
14514   plci->B1_resource = 0;
14515   plci->B1_facilities = 0;
14516
14517   plci->li_bchannel_id = 0;
14518   mixer_clear_config (plci);
14519
14520
14521   ec_clear_config (plci);
14522
14523
14524   dtmf_rec_clear_config (plci);
14525   dtmf_send_clear_config (plci);
14526   dtmf_parameter_clear_config (plci);
14527
14528   adv_voice_clear_config (plci);
14529   adjust_b_clear (plci);
14530 }
14531
14532
14533 static void clear_b1_config (PLCI   *plci)
14534 {
14535
14536   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14537     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14538     (char   *)(FILE_), __LINE__));
14539
14540   adv_voice_clear_config (plci);
14541   adjust_b_clear (plci);
14542
14543   ec_clear_config (plci);
14544
14545
14546   dtmf_rec_clear_config (plci);
14547   dtmf_send_clear_config (plci);
14548   dtmf_parameter_clear_config (plci);
14549
14550
14551   if ((plci->li_bchannel_id != 0)
14552    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14553   {
14554     mixer_clear_config (plci);
14555     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14556     plci->li_bchannel_id = 0;
14557   }
14558
14559   plci->B1_resource = 0;
14560   plci->B1_facilities = 0;
14561 }
14562
14563
14564 /* -----------------------------------------------------------------
14565                 XON protocol local helpers
14566    ----------------------------------------------------------------- */
14567 static void channel_flow_control_remove (PLCI   * plci) {
14568   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14569   word i;
14570   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14571     if (a->ch_flow_plci[i] == plci->Id) {
14572       a->ch_flow_plci[i] = 0;
14573       a->ch_flow_control[i] = 0;
14574     }
14575   }
14576 }
14577
14578 static void channel_x_on (PLCI   * plci, byte ch) {
14579   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14580   if (a->ch_flow_control[ch] & N_XON_SENT) {
14581     a->ch_flow_control[ch] &= ~N_XON_SENT;
14582   }
14583 }
14584
14585 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14586   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14587   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14588     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14589     a->ch_flow_plci[ch] = plci->Id;
14590     a->ch_flow_control_pending++;
14591   }
14592 }
14593
14594 static void channel_request_xon (PLCI   * plci, byte ch) {
14595   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14596
14597   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14598     a->ch_flow_control[ch] |= N_XON_REQ;
14599     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14600     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14601   }
14602 }
14603
14604 static void channel_xmit_extended_xon (PLCI   * plci) {
14605   DIVA_CAPI_ADAPTER   * a;
14606   int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14607   int i, one_requested = 0;
14608
14609   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14610     return;
14611   }
14612
14613   for (i = 0; i < max_ch; i++) {
14614     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14615         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14616         (plci->Id == a->ch_flow_plci[i])) {
14617       channel_request_xon (plci, (byte)i);
14618       one_requested = 1;
14619     }
14620   }
14621
14622   if (one_requested) {
14623     channel_xmit_xon (plci);
14624   }
14625 }
14626
14627 /*
14628   Try to xmit next X_ON
14629   */
14630 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14631   int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14632   int i;
14633
14634   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14635     return (0);
14636   }
14637
14638   if (a->last_flow_control_ch >= max_ch) {
14639     a->last_flow_control_ch = 1;
14640   }
14641   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14642     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14643         (plci->Id == a->ch_flow_plci[i])) {
14644       a->last_flow_control_ch = i+1;
14645       return (i);
14646     }
14647   }
14648
14649   for (i = 1; i < a->last_flow_control_ch; i++) {
14650     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14651         (plci->Id == a->ch_flow_plci[i])) {
14652       a->last_flow_control_ch = i+1;
14653       return (i);
14654     }
14655   }
14656
14657   return (0);
14658 }
14659
14660 static void channel_xmit_xon (PLCI   * plci) {
14661   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14662   byte ch;
14663
14664   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14665     return;
14666   }
14667   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14668     return;
14669   }
14670   a->ch_flow_control[ch] &= ~N_XON_REQ;
14671   a->ch_flow_control[ch] |= N_XON_SENT;
14672
14673   plci->NL.Req = plci->nl_req = (byte)N_XON;
14674   plci->NL.ReqCh         = ch;
14675   plci->NL.X             = plci->NData;
14676   plci->NL.XNum          = 1;
14677   plci->NData[0].P       = &plci->RBuffer[0];
14678   plci->NData[0].PLength = 0;
14679
14680   plci->adapter->request(&plci->NL);
14681 }
14682
14683 static int channel_can_xon (PLCI   * plci, byte ch) {
14684   APPL   * APPLptr;
14685   DIVA_CAPI_ADAPTER   * a;
14686   word NCCIcode;
14687   dword count;
14688   word Num;
14689   word i;
14690
14691   APPLptr = plci->appl;
14692   a = plci->adapter;
14693
14694   if (!APPLptr)
14695     return (0);
14696
14697   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14698
14699                 /* count all buffers within the Application pool    */
14700                 /* belonging to the same NCCI. XON if a first is    */
14701                 /* used.                                            */
14702   count = 0;
14703   Num = 0xffff;
14704   for(i=0; i<APPLptr->MaxBuffer; i++) {
14705     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14706     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14707   }
14708   if ((count > 2) || (Num == 0xffff)) {
14709     return (0);
14710   }
14711   return (1);
14712 }
14713
14714
14715 /*------------------------------------------------------------------*/
14716
14717 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14718 {
14719   return 1;
14720 }
14721
14722
14723
14724 /**********************************************************************************/
14725 /* function groups the listening applications according to the CIP mask and the   */
14726 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14727 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14728 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14729 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14730 /* OS specific part (per adapter).                                                */
14731 /**********************************************************************************/
14732 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14733 {
14734   word i,j,k,busy,group_found;
14735   dword info_mask_group[MAX_CIP_TYPES];
14736   dword cip_mask_group[MAX_CIP_TYPES];
14737   word appl_number_group_type[MAX_APPL];
14738   PLCI   *auxplci;
14739
14740   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14741
14742   if(!a->group_optimization_enabled)
14743   {
14744     dbug(1,dprintf("No group optimization"));
14745     return;
14746   }
14747
14748   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14749
14750   for(i=0;i<MAX_CIP_TYPES;i++)
14751   {
14752     info_mask_group[i] = 0;
14753     cip_mask_group [i] = 0;
14754   }
14755   for(i=0;i<MAX_APPL;i++)
14756   {
14757     appl_number_group_type[i] = 0;
14758   }
14759   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14760   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14761     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14762     {
14763       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14764       return; /* allow good application unfiltered access */
14765     }
14766   }
14767   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14768   {
14769     if(application[i].Id && a->CIP_Mask[i] )
14770     {
14771       for(k=0,busy=FALSE; k<a->max_plci; k++)
14772       {
14773         if(a->plci[k].Id) 
14774         {
14775           auxplci = &a->plci[k];
14776           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14777           {
14778             busy = TRUE;
14779             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14780           }
14781           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14782           {
14783             busy = TRUE;
14784             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14785           }
14786         }
14787       }
14788
14789       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14790       {
14791         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14792         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14793           appl_number_group_type[i] = MAX_CIP_TYPES;
14794           group_found=TRUE;
14795           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14796         }
14797         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14798         {                                      /* is group already present ?                  */
14799           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14800           group_found=TRUE;
14801           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]));
14802         }
14803         else if(!info_mask_group[j])
14804         {                                      /* establish a new group                       */
14805           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14806           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14807           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14808           group_found=TRUE;
14809           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]));
14810         }
14811       }
14812     }
14813   }
14814         
14815   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14816   {
14817     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14818     {
14819       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14820       {
14821         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14822       }
14823       else
14824       {
14825         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14826         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14827         {
14828           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14829           {
14830             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14831             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14832             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14833           }
14834         }
14835       }
14836     }
14837     else                                                 /* application should not get a call */
14838     {
14839       clear_group_ind_mask_bit (plci, i);
14840     }
14841   }
14842
14843 }
14844
14845
14846
14847 /* OS notifies the driver about a application Capi_Register */
14848 word CapiRegister(word id)
14849 {
14850   word i,j,appls_found;
14851
14852   PLCI   *plci;
14853   DIVA_CAPI_ADAPTER   *a;
14854
14855   for(i=0,appls_found=0; i<max_appl; i++)
14856   {
14857     if( application[i].Id && (application[i].Id!=id) )
14858     {
14859       appls_found++;                       /* an application has been found */
14860     }
14861   }
14862
14863   if(appls_found) return TRUE;
14864   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14865   {
14866     a = &adapter[i];
14867     if(a->request)
14868     {
14869       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14870       {
14871         if(!appls_found)           /* first application does a capi register   */
14872         {
14873           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14874           {
14875             plci = &a->plci[j-1];
14876             plci->command = 0;
14877             add_p(plci,OAD,"\x01\xfd");
14878             add_p(plci,CAI,"\x01\x80");
14879             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14880             add_p(plci,SHIFT|6,NULL);
14881             add_p(plci,SIN,"\x02\x00\x00");
14882             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14883             sig_req(plci,ASSIGN,DSIG_ID);
14884             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14885             sig_req(plci,SIG_CTRL,0);
14886             send_req(plci);
14887           }
14888         }
14889       }
14890     }
14891   }
14892   return FALSE;
14893 }
14894
14895 /*------------------------------------------------------------------*/
14896
14897 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14898
14899 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14900 {
14901  word i;
14902  /* Format of vswitch_t:
14903  0 byte length
14904  1 byte VSWITCHIE
14905  2 byte VSWITCH_REQ/VSWITCH_IND
14906  3 byte reserved
14907  4 word VSwitchcommand
14908  6 word returnerror
14909  8... Params
14910  */
14911  if(!plci ||
14912   !plci->appl ||
14913   !plci->State ||
14914   plci->Sig.Ind==NCR_FACILITY
14915   )
14916   return;
14917  
14918  for(i=0;i<MAX_MULTI_IE;i++)
14919  {
14920         if(!parms[i][0]) continue;
14921   if(parms[i][0]<7)
14922   {
14923    parms[i][0]=0; /* kill it */
14924    continue;
14925   }
14926   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14927   switch(parms[i][4])
14928   {
14929   case VSJOIN:
14930    if(!plci->relatedPTYPLCI ||
14931     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14932    { /* Error */
14933     break;
14934    }
14935    /* remember all necessary informations */
14936    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14937    {
14938     break;
14939    }
14940    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14941    {   /* first indication after ECT-Request on Consultation Call */
14942     plci->vswitchstate=parms[i][9];
14943     parms[i][9]=2; /* State */
14944     /* now ask first Call to join */
14945    }
14946    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14947    { /* Answer of VSWITCH_REQ from first Call */
14948     plci->vswitchstate=parms[i][9];
14949     /* tell consultation call to join
14950     and the protocol capabilities of the first call */
14951    }
14952    else
14953    { /* Error */
14954     break;
14955    }    
14956    plci->vsprot=parms[i][10]; /* protocol */
14957    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14958    /* send join request to related PLCI */
14959    parms[i][1]=VSWITCHIE;
14960    parms[i][2]=VSWITCH_REQ;
14961    
14962    plci->relatedPTYPLCI->command = 0;
14963    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14964    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14965    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14966    send_req(plci->relatedPTYPLCI);
14967    break;
14968   case VSTRANSPORT:
14969   default:
14970    if(plci->relatedPTYPLCI &&
14971     plci->vswitchstate==3 &&
14972     plci->relatedPTYPLCI->vswitchstate==3)
14973    {
14974     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14975     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14976     send_req(plci->relatedPTYPLCI);
14977    }
14978    break;
14979   }  
14980   parms[i][0]=0; /* kill it */
14981  }
14982 }
14983
14984
14985 /*------------------------------------------------------------------*/
14986
14987 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
14988   ENTITY e;
14989   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14990
14991   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14992     return (-1);
14993   }
14994
14995   pReq->xdi_dma_descriptor_operation.Req = 0;
14996   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14997
14998   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14999   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15000   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15001   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15002
15003   e.user[0] = plci->adapter->Id - 1;
15004   plci->adapter->request((ENTITY*)pReq);
15005
15006   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15007       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15008       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15009     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15010     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15011          plci->adapter->Id,
15012          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15013          *dma_magic));
15014     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15015   } else {
15016     dbug(1,dprintf("dma_alloc failed"));
15017     return (-1);
15018   }
15019 }
15020
15021 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15022   ENTITY e;
15023   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15024
15025   if (nr < 0) {
15026     return;
15027   }
15028
15029   pReq->xdi_dma_descriptor_operation.Req = 0;
15030   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15031
15032   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15033   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15034   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15035   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15036
15037   e.user[0] = plci->adapter->Id - 1;
15038   plci->adapter->request((ENTITY*)pReq);
15039
15040   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15041     dbug(1,dprintf("dma_free(%d)", nr));
15042   } else {
15043     dbug(1,dprintf("dma_free failed (%d)", nr));
15044   }
15045 }
15046
15047 /*------------------------------------------------------------------*/