Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[pandora-kernel.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3   Copyright (c) Eicon Networks, 2002.
4  *
5   This source file is supplied for the use with
6   Eicon Networks range of DIVA Server Adapters.
7  *
8   Eicon File Revision :    2.1
9  *
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2, or (at your option)
13   any later version.
14  *
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18   See the GNU General Public License for more details.
19  *
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67  */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
75 static void set_group_ind_mask (PLCI   *plci);
76 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
77 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL   *, CAPI_MSG   *);
82 static word api_parse(byte   *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
84 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI   *);
90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
92
93 void   callback(ENTITY   *);
94
95 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI   *, byte);
97 static void data_ack(PLCI   *, byte);
98 static void sig_ind(PLCI   *);
99 static void SendInfo(PLCI   *, dword, byte   * *, byte);
100 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
101 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
102
103 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
104
105 static void nl_ind(PLCI   *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER   *);
133 static void add_p(PLCI   *, byte, byte   *);
134 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
137 static void add_d(PLCI   *, word, byte   *);
138 static void add_ai(PLCI   *, API_PARSE *);
139 static word add_b1(PLCI   *, API_PARSE *, word, word);
140 static word add_b23(PLCI   *, API_PARSE *);
141 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI   *, byte, byte);
143 static void nl_req_ncci(PLCI   *, byte, byte);
144 static void send_req(PLCI   *);
145 static void send_data(PLCI   *);
146 static word plci_remove_check(PLCI   *);
147 static void listen_check(DIVA_CAPI_ADAPTER   *);
148 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI   *, word *, byte   **, byte);
151 static byte ie_compare(byte   *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
153 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
154
155 /*
156   XON protocol helpers
157   */
158 static void channel_flow_control_remove (PLCI   * plci);
159 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI   * plci, byte ch);
161 static void channel_request_xon (PLCI   * plci, byte ch);
162 static void channel_xmit_xon (PLCI   * plci);
163 static int channel_can_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI   * plci);
165
166 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
169 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
170 static void VoiceChannelOff(PLCI   *plci);
171 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
172 static void adv_voice_clear_config (PLCI   *plci);
173
174 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
189 static void init_b1_config (PLCI   *plci);
190 static void clear_b1_config (PLCI   *plci);
191
192 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI   *plci);
195 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
196 static void dtmf_parameter_write (PLCI   *plci);
197
198
199 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
201 static void mixer_clear_config (PLCI   *plci);
202 static void mixer_notify_update (PLCI   *plci, byte others);
203 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_remove (PLCI   *plci);
209
210
211 static void ec_command (dword Id, PLCI   *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
214
215
216 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
218
219
220 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
221 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231
232 void   sendf(APPL   *, word, dword, word, byte *, ...);
233 void   * TransmitBufferSet(APPL   * appl, dword ref);
234 void   * TransmitBufferGet(APPL   * appl, void   * p);
235 void TransmitBufferFree(APPL   * appl, void   * p);
236 void   * ReceiveBufferGet(APPL   * appl, int Num);
237
238 int fax_head_line_time (char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER   * adapter;
247 extern APPL   * application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260   word command;
261   byte * format;
262   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
263 } ftable[] = {
264   {_DATA_B3_R,                          "dwww",         data_b3_req},
265   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
266   {_INFO_R,                             "ss",           info_req},
267   {_INFO_I|RESPONSE,                    "",             info_res},
268   {_CONNECT_R,                          "wsssssssss",   connect_req},
269   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
270   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
271   {_DISCONNECT_R,                       "s",            disconnect_req},
272   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
273   {_LISTEN_R,                           "dddss",        listen_req},
274   {_ALERT_R,                            "s",            alert_req},
275   {_FACILITY_R,                         "ws",           facility_req},
276   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
277   {_CONNECT_B3_R,                       "s",            connect_b3_req},
278   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
279   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
280   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
282   {_RESET_B3_R,                         "s",            reset_b3_req},
283   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
284   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
286   {_SELECT_B_REQ,                       "s",            select_b_req},
287   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
289   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
290 };
291
292 static byte * cip_bc[29][2] = {
293   { "",                     ""                     }, /* 0 */
294   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303   { "",                     ""                     }, /* 10 */
304   { "",                     ""                     }, /* 11 */
305   { "",                     ""                     }, /* 12 */
306   { "",                     ""                     }, /* 13 */
307   { "",                     ""                     }, /* 14 */
308   { "",                     ""                     }, /* 15 */
309
310   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte * cip_hlc[29] = {
326   "",                           /* 0 */
327   "",                           /* 1 */
328   "",                           /* 2 */
329   "",                           /* 3 */
330   "",                           /* 4 */
331   "",                           /* 5 */
332   "",                           /* 6 */
333   "",                           /* 7 */
334   "",                           /* 8 */
335   "",                           /* 9 */
336   "",                           /* 10 */
337   "",                           /* 11 */
338   "",                           /* 12 */
339   "",                           /* 13 */
340   "",                           /* 14 */
341   "",                           /* 15 */
342
343   "\x02\x91\x81",               /* 16 */
344   "\x02\x91\x84",               /* 17 */
345   "\x02\x91\xa1",               /* 18 */
346   "\x02\x91\xa4",               /* 19 */
347   "\x02\x91\xa8",               /* 20 */
348   "\x02\x91\xb1",               /* 21 */
349   "\x02\x91\xb2",               /* 22 */
350   "\x02\x91\xb5",               /* 23 */
351   "\x02\x91\xb8",               /* 24 */
352   "\x02\x91\xc1",               /* 25 */
353   "\x02\x91\x81",               /* 26 */
354   "\x03\x91\xe0\x01",           /* 27 */
355   "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL   * appl, CAPI_MSG   * msg)
387 {
388   word i, j, k, l, n;
389   word ret;
390   byte c;
391   byte controller;
392   DIVA_CAPI_ADAPTER   * a;
393   PLCI   * plci;
394   NCCI   * ncci_ptr;
395   word ncci;
396   CAPI_MSG   *m;
397     API_PARSE msg_parms[MAX_MSG_PARMS+1];
398
399   if (msg->header.length < sizeof (msg->header) ||
400       msg->header.length > MAX_MSG_SIZE) {
401     dbug(1,dprintf("bad len"));
402     return _BAD_MSG;
403   }
404
405   controller = (byte)((msg->header.controller &0x7f)-1);
406
407   /* controller starts with 0 up to (max_adapter - 1) */
408   if ( controller >= max_adapter )
409   {
410     dbug(1,dprintf("invalid ctrl"));
411     return _BAD_MSG;
412   }
413   
414   a = &adapter[controller];
415   plci = NULL;
416   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417   {
418     dbug(1,dprintf("plci=%x",msg->header.plci));
419     plci = &a->plci[msg->header.plci-1];
420     ncci = GET_WORD(&msg->header.ncci);
421     if (plci->Id
422      && (plci->appl
423       || (plci->State == INC_CON_PENDING)
424       || (plci->State == INC_CON_ALERT)
425       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426      && ((ncci == 0)
427       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429     {
430       i = plci->msg_in_read_pos;
431       j = plci->msg_in_write_pos;
432       if (j >= i)
433       {
434         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435           i += MSG_IN_QUEUE_SIZE - j;
436         else
437           j = 0;
438       }
439       else
440       {
441
442         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444         if (i > MSG_IN_QUEUE_SIZE - n)
445           i = MSG_IN_QUEUE_SIZE - n + 1;
446         i -= j;
447       }
448
449       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451       {
452         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453           msg->header.length, plci->msg_in_write_pos,
454           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456         return _QUEUE_FULL;
457       }
458       c = false;
459       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
460        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461       {
462         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463           c = true;
464       }
465       if (msg->header.command == _DATA_B3_R)
466       {
467         if (msg->header.length < 20)
468         {
469           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470           return _BAD_MSG;
471         }
472         ncci_ptr = &(a->ncci[ncci]);
473         n = ncci_ptr->data_pending;
474         l = ncci_ptr->data_ack_pending;
475         k = plci->msg_in_read_pos;
476         while (k != plci->msg_in_write_pos)
477         {
478           if (k == plci->msg_in_wrap_pos)
479             k = 0;
480           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482           {
483             n++;
484             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485               l++;
486           }
487
488           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
489             MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491         }
492         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493         {
494           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497           return _QUEUE_FULL;
498         }
499         if (plci->req_in || plci->internal_command)
500         {
501           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
502            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503           {
504             dbug(0,dprintf("Q-FULL3(requeue)"));
505
506             return _QUEUE_FULL;
507           }
508           c = true;
509         }
510       }
511       else
512       {
513         if (plci->req_in || plci->internal_command)
514           c = true;
515         else
516         {
517           plci->command = msg->header.command;
518           plci->number = msg->header.number;
519         }
520       }
521       if (c)
522       {
523         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524           msg->header.command, plci->req_in, plci->internal_command,
525           msg->header.length, plci->msg_in_write_pos,
526           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527         if (j == 0)
528           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
530         for (i = 0; i < msg->header.length; i++)
531           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
532         if (m->header.command == _DATA_B3_R)
533         {
534
535           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
536
537         }
538
539         j = (j + 3) & 0xfffc;
540
541         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
542         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543         return 0;
544       }
545     }
546     else
547     {
548       plci = NULL;
549     }
550   }
551   dbug(1,dprintf("com=%x",msg->header.command));
552
553   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554   for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
555
556     if(ftable[i].command==msg->header.command) {
557       /* break loop if the message is correct, otherwise continue scan  */
558       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
559       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
560         ret = 0;
561         break;
562       }
563       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
564     }
565   }
566   if(ret) {
567     dbug(1,dprintf("BAD_MSG"));
568     if(plci) plci->command = 0;
569     return ret;
570   }
571
572
573   c = ftable[i].function(GET_DWORD(&msg->header.controller),
574                          msg->header.number,
575                          a,
576                          plci,
577                          appl,
578                          msg_parms);
579
580   channel_xmit_extended_xon (plci);
581
582   if(c==1) send_req(plci);
583   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584   if(plci && !plci->req_in) plci->command = 0;
585   return 0;
586 }
587
588
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages             */
591 /*------------------------------------------------------------------*/
592
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
594 {
595   word i;
596   word p;
597
598   for(i=0,p=0; format[i]; i++) {
599     if(parms)
600     {
601       parms[i].info = &msg[p];
602     }
603     switch(format[i]) {
604     case 'b':
605       p +=1;
606       break;
607     case 'w':
608       p +=2;
609       break;
610     case 'd':
611       p +=4;
612       break;
613     case 's':
614       if(msg[p]==0xff) {
615         parms[i].info +=2;
616         parms[i].length = msg[p+1] + (msg[p+2]<<8);
617         p +=(parms[i].length +3);
618       }
619       else {
620         parms[i].length = msg[p];
621         p +=(parms[i].length +1);
622       }
623       break;
624     }
625
626     if(p>length) return true;
627   }
628   if(parms) parms[i].info = NULL;
629   return false;
630 }
631
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
633 {
634   word i, j, n = 0;
635   byte   *p;
636
637   p = out->info;
638   for (i = 0; format[i] != '\0'; i++)
639   {
640     out->parms[i].info = p;
641     out->parms[i].length = in[i].length;
642     switch (format[i])
643     {
644     case 'b':
645       n = 1;
646       break;
647     case 'w':
648       n = 2;
649       break;
650     case 'd':
651       n = 4;
652       break;
653     case 's':
654       n = in[i].length + 1;
655       break;
656     }
657     for (j = 0; j < n; j++)
658       *(p++) = in[i].info[j];
659   }
660   out->parms[i].info = NULL;
661   out->parms[i].length = 0;
662 }
663
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
665 {
666   word i;
667
668   i = 0;
669   do
670   {
671     out[i].info = in->parms[i].info;
672     out[i].length = in->parms[i].length;
673   } while (in->parms[i++].info);
674 }
675
676
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function                                             */
679 /*------------------------------------------------------------------*/
680
681 word api_remove_start(void)
682 {
683   word i;
684   word j;
685
686   if(!remove_started) {
687     remove_started = true;
688     for(i=0;i<max_adapter;i++) {
689       if(adapter[i].request) {
690         for(j=0;j<adapter[i].max_plci;j++) {
691           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692         }
693       }
694     }
695     return 1;
696   }
697   else {
698     for(i=0;i<max_adapter;i++) {
699       if(adapter[i].request) {
700         for(j=0;j<adapter[i].max_plci;j++) {
701           if(adapter[i].plci[j].Sig.Id) return 1;
702         }
703       }
704     }
705   }
706   api_remove_complete();
707   return 0;
708 }
709
710
711 /*------------------------------------------------------------------*/
712 /* internal command queue                                           */
713 /*------------------------------------------------------------------*/
714
715 static void init_internal_command_queue (PLCI   *plci)
716 {
717   word i;
718
719   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
720     (char   *)(FILE_), __LINE__));
721
722   plci->internal_command = 0;
723   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724     plci->internal_command_queue[i] = NULL;
725 }
726
727
728 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
729 {
730   word i;
731
732   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
733     UnMapId (Id), (char   *)(FILE_), __LINE__));
734
735   if (plci->internal_command == 0)
736   {
737     plci->internal_command_queue[0] = command_function;
738     (* command_function)(Id, plci, OK);
739   }
740   else
741   {
742     i = 1;
743     while (plci->internal_command_queue[i] != NULL)
744       i++;
745     plci->internal_command_queue[i] = command_function;
746   }
747 }
748
749
750 static void next_internal_command (dword Id, PLCI   *plci)
751 {
752   word i;
753
754   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
755     UnMapId (Id), (char   *)(FILE_), __LINE__));
756
757   plci->internal_command = 0;
758   plci->internal_command_queue[0] = NULL;
759   while (plci->internal_command_queue[1] != NULL)
760   {
761     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
763     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764     (*(plci->internal_command_queue[0]))(Id, plci, OK);
765     if (plci->internal_command != 0)
766       return;
767     plci->internal_command_queue[0] = NULL;
768   }
769 }
770
771
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function                                    */
774 /*------------------------------------------------------------------*/
775
776 static dword ncci_mapping_bug = 0;
777
778 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
779 {
780   DIVA_CAPI_ADAPTER   *a;
781   word ncci, i, j, k;
782
783   a = plci->adapter;
784   if (!ch || a->ch_ncci[ch])
785   {
786     ncci_mapping_bug++;
787     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789     ncci = ch;
790   }
791   else
792   {
793     if (force_ncci)
794       ncci = force_ncci;
795     else
796     {
797       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
798         ncci = ch;
799       else
800       {
801         ncci = 1;
802         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
803           ncci++;
804         if (ncci == MAX_NCCI+1)
805         {
806           ncci_mapping_bug++;
807           i = 1;
808           do
809           {
810             j = 1;
811             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
812               j++;
813             k = j;
814             if (j < MAX_NCCI+1)
815             {
816               do
817               {
818                 j++;
819               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
820             }
821           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
822           if (i < MAX_NL_CHANNEL+1)
823           {
824             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825               ncci_mapping_bug, ch, force_ncci, i, k, j));
826           }
827           else
828           {
829             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
830               ncci_mapping_bug, ch, force_ncci));
831           }
832           ncci = ch;
833         }
834       }
835       a->ncci_plci[ncci] = plci->Id;
836       a->ncci_state[ncci] = IDLE;
837       if (!plci->ncci_ring_list)
838         plci->ncci_ring_list = ncci;
839       else
840         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842     }
843     a->ncci_ch[ncci] = ch;
844     a->ch_ncci[ch] = (byte) ncci;
845     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846       ncci_mapping_bug, ch, force_ncci, ch, ncci));
847   }
848   return (ncci);
849 }
850
851
852 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
853 {
854   DIVA_CAPI_ADAPTER   *a;
855   APPL   *appl;
856   word i, ncci_code;
857   dword Id;
858
859   a = plci->adapter;
860   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861   if (ncci)
862   {
863     if (a->ncci_plci[ncci] == plci->Id)
864     {
865       if (!plci->appl)
866       {
867         ncci_mapping_bug++;
868         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
869           ncci_mapping_bug, Id));
870       }
871       else
872       {
873         appl = plci->appl;
874         ncci_code = ncci | (((word) a->Id) << 8);
875         for (i = 0; i < appl->MaxBuffer; i++)
876         {
877           if ((appl->DataNCCI[i] == ncci_code)
878            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879           {
880             appl->DataNCCI[i] = 0;
881           }
882         }
883       }
884     }
885   }
886   else
887   {
888     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
889     {
890       if (a->ncci_plci[ncci] == plci->Id)
891       {
892         if (!plci->appl)
893         {
894           ncci_mapping_bug++;
895           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
896             ncci_mapping_bug, Id));
897         }
898         else
899         {
900           appl = plci->appl;
901           ncci_code = ncci | (((word) a->Id) << 8);
902           for (i = 0; i < appl->MaxBuffer; i++)
903           {
904             if ((appl->DataNCCI[i] == ncci_code)
905              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906             {
907               appl->DataNCCI[i] = 0;
908             }
909           }
910         }
911       }
912     }
913   }
914 }
915
916
917 static void cleanup_ncci_data (PLCI   *plci, word ncci)
918 {
919   NCCI   *ncci_ptr;
920
921   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922   {
923     ncci_ptr = &(plci->adapter->ncci[ncci]);
924     if (plci->appl)
925     {
926       while (ncci_ptr->data_pending != 0)
927       {
928         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930         (ncci_ptr->data_out)++;
931         if (ncci_ptr->data_out == MAX_DATA_B3)
932           ncci_ptr->data_out = 0;
933         (ncci_ptr->data_pending)--;
934       }
935     }
936     ncci_ptr->data_out = 0;
937     ncci_ptr->data_pending = 0;
938     ncci_ptr->data_ack_out = 0;
939     ncci_ptr->data_ack_pending = 0;
940   }
941 }
942
943
944 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
945 {
946   DIVA_CAPI_ADAPTER   *a;
947   dword Id;
948   word i;
949
950   a = plci->adapter;
951   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952   if (!preserve_ncci)
953     ncci_free_receive_buffers (plci, ncci);
954   if (ncci)
955   {
956     if (a->ncci_plci[ncci] != plci->Id)
957     {
958       ncci_mapping_bug++;
959       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960         ncci_mapping_bug, Id, preserve_ncci));
961     }
962     else
963     {
964       cleanup_ncci_data (plci, ncci);
965       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967       a->ch_ncci[a->ncci_ch[ncci]] = 0;
968       if (!preserve_ncci)
969       {
970         a->ncci_ch[ncci] = 0;
971         a->ncci_plci[ncci] = 0;
972         a->ncci_state[ncci] = IDLE;
973         i = plci->ncci_ring_list;
974         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975           i = a->ncci_next[i];
976         if ((i != 0) && (a->ncci_next[i] == ncci))
977         {
978           if (i == ncci)
979             plci->ncci_ring_list = 0;
980           else if (plci->ncci_ring_list == ncci)
981             plci->ncci_ring_list = i;
982           a->ncci_next[i] = a->ncci_next[ncci];
983         }
984         a->ncci_next[ncci] = 0;
985       }
986     }
987   }
988   else
989   {
990     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
991     {
992       if (a->ncci_plci[ncci] == plci->Id)
993       {
994         cleanup_ncci_data (plci, ncci);
995         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997         a->ch_ncci[a->ncci_ch[ncci]] = 0;
998         if (!preserve_ncci)
999         {
1000           a->ncci_ch[ncci] = 0;
1001           a->ncci_plci[ncci] = 0;
1002           a->ncci_state[ncci] = IDLE;
1003           a->ncci_next[ncci] = 0;
1004         }
1005       }
1006     }
1007     if (!preserve_ncci)
1008       plci->ncci_ring_list = 0;
1009   }
1010 }
1011
1012
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function                                             */
1015 /*------------------------------------------------------------------*/
1016
1017 static void plci_free_msg_in_queue (PLCI   *plci)
1018 {
1019   word i;
1020
1021   if (plci->appl)
1022   {
1023     i = plci->msg_in_read_pos;
1024     while (i != plci->msg_in_write_pos)
1025     {
1026       if (i == plci->msg_in_wrap_pos)
1027         i = 0;
1028       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029       {
1030
1031         TransmitBufferFree (plci->appl,
1032           (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033
1034       }
1035
1036       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1037         MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039     }
1040   }
1041   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044 }
1045
1046
1047 static void plci_remove(PLCI   * plci)
1048 {
1049
1050   if(!plci) {
1051     dbug(1,dprintf("plci_remove(no plci)"));
1052     return;
1053   }
1054   init_internal_command_queue (plci);
1055   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1056   if(plci_remove_check(plci))
1057   {
1058     return;
1059   }
1060   if (plci->Sig.Id == 0xff)
1061   {
1062     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063     if (plci->NL.Id && !plci->nl_remove_id)
1064     {
1065       nl_req_ncci(plci,REMOVE,0);
1066       send_req(plci);
1067     }
1068   }
1069   else
1070   {
1071     if (!plci->sig_remove_id
1072      && (plci->Sig.Id
1073       || (plci->req_in!=plci->req_out)
1074       || (plci->nl_req || plci->sig_req)))
1075     {
1076       sig_req(plci,HANGUP,0);
1077       send_req(plci);
1078     }
1079   }
1080   ncci_remove (plci, 0, false);
1081   plci_free_msg_in_queue (plci);
1082
1083   plci->channels = 0;
1084   plci->appl = NULL;
1085   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086     plci->State = OUTG_DIS_PENDING;
1087 }
1088
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers                               */
1091 /*------------------------------------------------------------------*/
1092
1093 static void set_group_ind_mask (PLCI   *plci)
1094 {
1095   word i;
1096
1097   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098     plci->group_optimization_mask_table[i] = 0xffffffffL;
1099 }
1100
1101 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1102 {
1103   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104 }
1105
1106 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1107 {
1108   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109 }
1110
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1113 /*------------------------------------------------------------------*/
1114
1115 static void clear_c_ind_mask (PLCI   *plci)
1116 {
1117   word i;
1118
1119   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120     plci->c_ind_mask_table[i] = 0;
1121 }
1122
1123 static byte c_ind_mask_empty (PLCI   *plci)
1124 {
1125   word i;
1126
1127   i = 0;
1128   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129     i++;
1130   return (i == C_IND_MASK_DWORDS);
1131 }
1132
1133 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1134 {
1135   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136 }
1137
1138 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1139 {
1140   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141 }
1142
1143 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1144 {
1145   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146 }
1147
1148 static void dump_c_ind_mask (PLCI   *plci)
1149 {
1150 static char hex_digit_table[0x10] =
1151   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1152   word i, j, k;
1153   dword d;
1154     char *p;
1155     char buf[40];
1156
1157   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158   {
1159     p = buf + 36;
1160     *p = '\0';
1161     for (j = 0; j < 4; j++)
1162     {
1163       if (i+j < C_IND_MASK_DWORDS)
1164       {
1165         d = plci->c_ind_mask_table[i+j];
1166         for (k = 0; k < 8; k++)
1167         {
1168           *(--p) = hex_digit_table[d & 0xf];
1169           d >>= 4;
1170         }
1171       }
1172       else if (i != 0)
1173       {
1174         for (k = 0; k < 8; k++)
1175           *(--p) = ' ';
1176       }
1177       *(--p) = ' ';
1178     }
1179     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1180   }
1181 }
1182
1183
1184
1185
1186
1187 #define dump_plcis(a)
1188
1189
1190
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message                            */
1193 /*------------------------------------------------------------------*/
1194
1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196                         PLCI *plci, APPL *appl, API_PARSE *parms)
1197 {
1198   word ch;
1199   word i;
1200   word Info;
1201   word CIP;
1202   byte LinkLayer;
1203   API_PARSE * ai;
1204   API_PARSE * bp;
1205     API_PARSE ai_parms[5];
1206   word channel = 0;
1207   dword ch_mask;
1208   byte m;
1209   static byte esc_chi[35] = {0x02,0x18,0x01};
1210   static byte lli[2] = {0x01,0x00};
1211   byte noCh = 0;
1212   word dir = 0;
1213   byte   *p_chi = "";
1214
1215   for(i=0;i<5;i++) ai_parms[i].length = 0;
1216
1217   dbug(1,dprintf("connect_req(%d)",parms->length));
1218   Info = _WRONG_IDENTIFIER;
1219   if(a)
1220   {
1221     if(a->adapter_disabled)
1222     {
1223       dbug(1,dprintf("adapter disabled"));
1224       Id = ((word)1<<8)|a->Id;
1225       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1226       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1227       return false;
1228     }
1229     Info = _OUT_OF_PLCI;
1230     if((i=get_plci(a)))
1231     {
1232       Info = 0;
1233       plci = &a->plci[i-1];
1234       plci->appl = appl;
1235       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1236       /* check 'external controller' bit for codec support */
1237       if(Id & EXT_CONTROLLER)
1238       {
1239         if(AdvCodecSupport(a, plci, appl, 0) )
1240         {
1241           plci->Id = 0;
1242           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1243           return 2;
1244         }
1245       }
1246       ai = &parms[9];
1247       bp = &parms[5];
1248       ch = 0;
1249       if(bp->length)LinkLayer = bp->info[3];
1250       else LinkLayer = 0;
1251       if(ai->length)
1252       {
1253         ch=0xffff;
1254         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1255         {
1256           ch = 0;
1257           if(ai_parms[0].length)
1258           {
1259             ch = GET_WORD(ai_parms[0].info+1);
1260             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1261             if(ch==4) /* explizit CHI in message */
1262             {
1263               /* check length of B-CH struct */
1264               if((ai_parms[0].info)[3]>=1)
1265               {
1266                 if((ai_parms[0].info)[4]==CHI)
1267                 {
1268                   p_chi = &((ai_parms[0].info)[5]);
1269                 }
1270                 else
1271                 {
1272                   p_chi = &((ai_parms[0].info)[3]);
1273                 }
1274                 if(p_chi[0]>35) /* check length of channel ID */
1275                 {
1276                   Info = _WRONG_MESSAGE_FORMAT;    
1277                 }
1278               }
1279               else Info = _WRONG_MESSAGE_FORMAT;    
1280             }
1281
1282             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1283             {
1284               dir = GET_WORD(ai_parms[0].info+3);
1285               ch_mask = 0;
1286               m = 0x3f;
1287               for(i=0; i+5<=ai_parms[0].length; i++)
1288               {
1289                 if(ai_parms[0].info[i+5]!=0)
1290                 {
1291                   if((ai_parms[0].info[i+5] | m) != 0xff)
1292                     Info = _WRONG_MESSAGE_FORMAT;
1293                   else
1294                   {
1295                     if (ch_mask == 0)
1296                       channel = i;
1297                     ch_mask |= 1L << i;
1298                   }
1299                 }
1300                 m = 0;
1301               }
1302               if (ch_mask == 0)
1303                 Info = _WRONG_MESSAGE_FORMAT;
1304               if (!Info)
1305               {
1306                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1307                 {
1308                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1309                   for(i=0; i+5<=ai_parms[0].length; i++)
1310                     esc_chi[i+3] = ai_parms[0].info[i+5];
1311                 }
1312                 else
1313                   esc_chi[0] = 2;
1314                 esc_chi[2] = (byte)channel;
1315                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1316                 add_p(plci,LLI,lli);
1317                 add_p(plci,ESC,esc_chi);
1318                 plci->State = LOCAL_CONNECT;
1319                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1320               }
1321             }
1322           }
1323         }
1324         else  Info = _WRONG_MESSAGE_FORMAT;
1325       }
1326
1327       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1328       plci->command = _CONNECT_R;
1329       plci->number = Number;
1330       /* x.31 or D-ch free SAPI in LinkLayer? */
1331       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1332       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1333       {
1334         /* B-channel used for B3 connections (ch==0), or no B channel    */
1335         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1336         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1337         else     Info = add_b1(plci,&parms[5],ch,0); 
1338         add_s(plci,OAD,&parms[2]);
1339         add_s(plci,OSA,&parms[4]);
1340         add_s(plci,BC,&parms[6]);
1341         add_s(plci,LLC,&parms[7]);
1342         add_s(plci,HLC,&parms[8]);
1343         CIP = GET_WORD(parms[0].info);
1344         if (a->Info_Mask[appl->Id-1] & 0x200)
1345         {
1346           /* early B3 connect (CIP mask bit 9) no release after a disc */
1347           add_p(plci,LLI,"\x01\x01");
1348         }
1349         if(GET_WORD(parms[0].info)<29) {
1350           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1351           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1352         }
1353         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1354         sig_req(plci,ASSIGN,DSIG_ID);
1355       }
1356       else if(ch==1) {
1357
1358         /* D-Channel used for B3 connections */
1359         plci->Sig.Id = 0xff;
1360         Info = 0;
1361       }
1362
1363       if(!Info && ch!=2 && !noCh ) {
1364         Info = add_b23(plci,&parms[5]);
1365         if(!Info) {
1366           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1367         }
1368       }
1369
1370       if(!Info)
1371       {
1372         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1373         {
1374           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1375           {
1376             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1377             plci->spoofed_msg = CALL_REQ;
1378             plci->internal_command = BLOCK_PLCI;
1379             plci->command = 0;
1380             dbug(1,dprintf("Spoof"));
1381             send_req(plci);
1382             return false;
1383           }
1384           if(ch==4)add_p(plci,CHI,p_chi);
1385           add_s(plci,CPN,&parms[1]);
1386           add_s(plci,DSA,&parms[3]);
1387           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1388           add_ai(plci,&parms[9]);
1389           if(!dir)sig_req(plci,CALL_REQ,0);
1390           else
1391           {
1392             plci->command = PERM_LIST_REQ;
1393             plci->appl = appl;
1394             sig_req(plci,LISTEN_REQ,0);
1395             send_req(plci);
1396             return false;
1397           }
1398         }
1399         send_req(plci);
1400         return false;
1401       }
1402       plci->Id = 0;
1403     }
1404   }
1405   sendf(appl,
1406         _CONNECT_R|CONFIRM,
1407         Id,
1408         Number,
1409         "w",Info);
1410   return 2;
1411 }
1412
1413 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1414                         PLCI *plci, APPL *appl, API_PARSE *parms)
1415 {
1416   word i, Info;
1417   word Reject;
1418   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1420   API_PARSE * ai;
1421     API_PARSE ai_parms[5];
1422   word ch=0;
1423
1424   if(!plci) {
1425     dbug(1,dprintf("connect_res(no plci)"));
1426     return 0;  /* no plci, no send */
1427   }
1428
1429   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430   for(i=0;i<5;i++) ai_parms[i].length = 0;
1431   ai = &parms[5];
1432   dbug(1,dprintf("ai->length=%d",ai->length));
1433
1434   if(ai->length)
1435   {
1436     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1437     {
1438       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1439       ch = 0;
1440       if(ai_parms[0].length)
1441       {
1442         ch = GET_WORD(ai_parms[0].info+1);
1443         dbug(1,dprintf("BCH-I=0x%x",ch));
1444       }
1445     }
1446   }
1447
1448   if(plci->State==INC_CON_CONNECTED_ALERT)
1449   {
1450     dbug(1,dprintf("Connected Alert Call_Res"));
1451     if (a->Info_Mask[appl->Id-1] & 0x200)
1452     {
1453     /* early B3 connect (CIP mask bit 9) no release after a disc */
1454       add_p(plci,LLI,"\x01\x01");
1455     }
1456     add_s(plci, CONN_NR, &parms[2]);
1457     add_s(plci, LLC, &parms[4]);
1458     add_ai(plci, &parms[5]);
1459     plci->State = INC_CON_ACCEPT;
1460     sig_req(plci, CALL_RES,0);
1461     return 1;
1462   }
1463   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465     dump_c_ind_mask (plci);
1466     Reject = GET_WORD(parms[0].info);
1467     dbug(1,dprintf("Reject=0x%x",Reject));
1468     if(Reject) 
1469     {
1470       if(c_ind_mask_empty (plci)) 
1471       {
1472         if((Reject&0xff00)==0x3400) 
1473         {
1474           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475           add_p(plci,ESC,esc_t);
1476           add_ai(plci, &parms[5]);
1477           sig_req(plci,REJECT,0);
1478         }      
1479         else if(Reject==1 || Reject>9) 
1480         {
1481           add_ai(plci, &parms[5]);
1482           sig_req(plci,HANGUP,0);
1483         }
1484         else 
1485         {
1486           esc_t[2] = cau_t[(Reject&0x000f)];
1487           add_p(plci,ESC,esc_t);
1488           add_ai(plci, &parms[5]);
1489           sig_req(plci,REJECT,0);
1490         }
1491         plci->appl = appl;
1492       }
1493       else 
1494       {
1495         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1496       }
1497     }
1498     else {
1499       plci->appl = appl;
1500       if(Id & EXT_CONTROLLER){
1501         if(AdvCodecSupport(a, plci, appl, 0)){
1502           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503           sig_req(plci,HANGUP,0);
1504           return 1;
1505         }
1506         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1507         {
1508           Info = add_b23(plci, &parms[1]);
1509           if (Info)
1510           {
1511             dbug(1,dprintf("connect_res(error from add_b23)"));
1512             sig_req(plci,HANGUP,0);
1513             return 1;
1514           }
1515           if(plci->adv_nl)
1516           {
1517             nl_req_ncci(plci, ASSIGN, 0);
1518           }
1519         }
1520       }
1521       else
1522       {
1523         plci->tel = 0;
1524         if(ch!=2)
1525         {
1526           Info = add_b23(plci, &parms[1]);
1527           if (Info)
1528           {
1529             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530             sig_req(plci,HANGUP,0);
1531             return 1;
1532           }
1533         }
1534         nl_req_ncci(plci, ASSIGN, 0);
1535       }
1536
1537       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1538       {
1539         api_save_msg(parms, "wsssss", &plci->saved_msg);
1540         plci->spoofed_msg = CALL_RES;
1541         plci->internal_command = BLOCK_PLCI;
1542         plci->command = 0;
1543         dbug(1,dprintf("Spoof"));
1544       }
1545       else
1546       {
1547         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548         if (a->Info_Mask[appl->Id-1] & 0x200)
1549         {
1550           /* early B3 connect (CIP mask bit 9) no release after a disc */
1551           add_p(plci,LLI,"\x01\x01");
1552         }
1553         add_s(plci, CONN_NR, &parms[2]);
1554         add_s(plci, LLC, &parms[4]);
1555         add_ai(plci, &parms[5]);
1556         plci->State = INC_CON_ACCEPT;
1557         sig_req(plci, CALL_RES,0);
1558       }
1559
1560       for(i=0; i<max_appl; i++) {
1561         if(test_c_ind_mask_bit (plci, i)) {
1562           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1563         }
1564       }
1565     }
1566   }
1567   return 1;
1568 }
1569
1570 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1571                           PLCI *plci, APPL *appl, API_PARSE *msg)
1572 {
1573   dbug(1,dprintf("connect_a_res"));
1574   return false;
1575 }
1576
1577 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1578                            PLCI *plci, APPL *appl, API_PARSE *msg)
1579 {
1580   word Info;
1581   word i;
1582
1583   dbug(1,dprintf("disconnect_req"));
1584
1585   Info = _WRONG_IDENTIFIER;
1586
1587   if(plci)
1588   {
1589     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1590     {
1591       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1592       plci->appl = appl;
1593       for(i=0; i<max_appl; i++)
1594       {
1595         if(test_c_ind_mask_bit (plci, i))
1596           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1597       }
1598       plci->State = OUTG_DIS_PENDING;
1599     }
1600     if(plci->Sig.Id && plci->appl)
1601     {
1602       Info = 0;
1603         if(plci->Sig.Id!=0xff)
1604         {
1605           if(plci->State!=INC_DIS_PENDING)
1606           {
1607             add_ai(plci, &msg[0]);
1608             sig_req(plci,HANGUP,0);
1609             plci->State = OUTG_DIS_PENDING;
1610             return 1;
1611           }
1612         }
1613         else
1614         {
1615           if (plci->NL.Id && !plci->nl_remove_id)
1616           {
1617             mixer_remove (plci);
1618             nl_req_ncci(plci,REMOVE,0);
1619           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1620           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1621           plci->State = INC_DIS_PENDING;
1622           }
1623           return 1;
1624         }
1625       }
1626     }
1627
1628   if(!appl)  return false;
1629   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1630   return false;
1631 }
1632
1633 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1634                            PLCI *plci, APPL *appl, API_PARSE *msg)
1635 {
1636   dbug(1,dprintf("disconnect_res"));
1637   if(plci)
1638   {
1639         /* clear ind mask bit, just in case of collsion of          */
1640         /* DISCONNECT_IND and CONNECT_RES                           */
1641     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1642     ncci_free_receive_buffers (plci, 0);
1643     if(plci_remove_check(plci))
1644     {
1645       return 0;
1646     }
1647     if(plci->State==INC_DIS_PENDING
1648     || plci->State==SUSPENDING) {
1649       if(c_ind_mask_empty (plci)) {
1650         if(plci->State!=SUSPENDING)plci->State = IDLE;
1651         dbug(1,dprintf("chs=%d",plci->channels));
1652         if(!plci->channels) {
1653           plci_remove(plci);
1654         }
1655       }
1656     }
1657   }
1658   return 0;
1659 }
1660
1661 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1662                        PLCI *plci, APPL *appl, API_PARSE *parms)
1663 {
1664   word Info;
1665   byte i;
1666
1667   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1668
1669   Info = _WRONG_IDENTIFIER;
1670   if(a) {
1671     Info = 0;
1672     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1673     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1674     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1675     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1676       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1677     }
1678
1679     /* check if external controller listen and switch listen on or off*/
1680     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1681       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1682         dummy_plci.State = IDLE;
1683         a->codec_listen[appl->Id-1] = &dummy_plci;
1684         a->TelOAD[0] = (byte)(parms[3].length);
1685         for(i=1;parms[3].length>=i && i<22;i++) {
1686           a->TelOAD[i] = parms[3].info[i];
1687         }
1688         a->TelOAD[i] = 0;
1689         a->TelOSA[0] = (byte)(parms[4].length);
1690         for(i=1;parms[4].length>=i && i<22;i++) {
1691           a->TelOSA[i] = parms[4].info[i];
1692         }
1693         a->TelOSA[i] = 0;
1694       }
1695       else Info = 0x2002; /* wrong controller, codec not supported */
1696     }
1697     else{               /* clear listen */
1698       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1699     }
1700   }
1701   sendf(appl,
1702         _LISTEN_R|CONFIRM,
1703         Id,
1704         Number,
1705         "w",Info);
1706
1707   if (a) listen_check(a);
1708   return false;
1709 }
1710
1711 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1712                      PLCI *plci, APPL *appl, API_PARSE *msg)
1713 {
1714   word i;
1715   API_PARSE * ai;
1716   PLCI   * rc_plci = NULL;
1717     API_PARSE ai_parms[5];
1718   word Info = 0;
1719
1720   dbug(1,dprintf("info_req"));
1721   for(i=0;i<5;i++) ai_parms[i].length = 0;
1722
1723   ai = &msg[1];
1724
1725   if(ai->length)
1726   {
1727     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1728     {
1729       dbug(1,dprintf("AddInfo wrong"));
1730       Info = _WRONG_MESSAGE_FORMAT;
1731     }
1732   }
1733   if(!a) Info = _WRONG_STATE;
1734
1735   if(!Info && plci)
1736   {                /* no fac, with CPN, or KEY */
1737     rc_plci = plci;
1738     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1739     {
1740       /* overlap sending option */
1741       dbug(1,dprintf("OvlSnd"));
1742       add_s(plci,CPN,&msg[0]);
1743       add_s(plci,KEY,&ai_parms[1]);
1744       sig_req(plci,INFO_REQ,0);
1745       send_req(plci);
1746       return false;
1747     }
1748
1749     if(plci->State && ai_parms[2].length)
1750     {
1751       /* User_Info option */
1752       dbug(1,dprintf("UUI"));
1753       add_s(plci,UUI,&ai_parms[2]);
1754       sig_req(plci,USER_DATA,0);
1755     }
1756     else if(plci->State && ai_parms[3].length)
1757     {
1758       /* Facility option */
1759       dbug(1,dprintf("FAC"));
1760       add_s(plci,CPN,&msg[0]);
1761       add_ai(plci, &msg[1]);
1762       sig_req(plci,FACILITY_REQ,0);
1763     }
1764     else
1765     {
1766       Info = _WRONG_STATE;
1767     }
1768   }
1769   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1770   {
1771     /* NCR_Facility option -> send UUI and Keypad too */
1772     dbug(1,dprintf("NCR_FAC"));
1773     if((i=get_plci(a)))
1774     {
1775       rc_plci = &a->plci[i-1];
1776       appl->NullCREnable  = true;
1777       rc_plci->internal_command = C_NCR_FAC_REQ;
1778       rc_plci->appl = appl;
1779       add_p(rc_plci,CAI,"\x01\x80");
1780       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1781       sig_req(rc_plci,ASSIGN,DSIG_ID);
1782       send_req(rc_plci);
1783     }
1784     else
1785     {
1786       Info = _OUT_OF_PLCI;
1787     }
1788
1789     if(!Info)
1790     {
1791       add_s(rc_plci,CPN,&msg[0]);
1792       add_ai(rc_plci, &msg[1]);
1793       sig_req(rc_plci,NCR_FACILITY,0);
1794       send_req(rc_plci);
1795       return false;
1796      /* for application controlled supplementary services    */
1797     }
1798   }
1799
1800   if (!rc_plci)
1801   {
1802     Info = _WRONG_MESSAGE_FORMAT;
1803   }
1804
1805   if(!Info)
1806   {
1807     send_req(rc_plci);
1808   }
1809   else
1810   {  /* appl is not assigned to a PLCI or error condition */
1811     dbug(1,dprintf("localInfoCon"));
1812     sendf(appl,
1813           _INFO_R|CONFIRM,
1814           Id,
1815           Number,
1816           "w",Info);
1817   }
1818   return false;
1819 }
1820
1821 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1822                      PLCI *plci, APPL *appl, API_PARSE *msg)
1823 {
1824   dbug(1,dprintf("info_res"));
1825   return false;
1826 }
1827
1828 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1829                       PLCI *plci, APPL *appl, API_PARSE *msg)
1830 {
1831   word Info;
1832   byte ret;
1833
1834   dbug(1,dprintf("alert_req"));
1835
1836   Info = _WRONG_IDENTIFIER;
1837   ret = false;
1838   if(plci) {
1839     Info = _ALERT_IGNORED;
1840     if(plci->State!=INC_CON_ALERT) {
1841       Info = _WRONG_STATE;
1842       if(plci->State==INC_CON_PENDING) {
1843         Info = 0;
1844         plci->State=INC_CON_ALERT;
1845         add_ai(plci, &msg[0]);
1846         sig_req(plci,CALL_ALERT,0);
1847         ret = 1;
1848       }
1849     }
1850   }
1851   sendf(appl,
1852         _ALERT_R|CONFIRM,
1853         Id,
1854         Number,
1855         "w",Info);
1856   return ret;
1857 }
1858
1859 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1860                          PLCI *plci, APPL *appl, API_PARSE *msg)
1861 {
1862   word Info = 0;
1863   word i    = 0;
1864
1865   word selector;
1866   word SSreq;
1867   long relatedPLCIvalue;
1868   DIVA_CAPI_ADAPTER   * relatedadapter;
1869   byte * SSparms  = "";
1870     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1871     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1872   API_PARSE * parms;
1873     API_PARSE ss_parms[11];
1874   PLCI   *rplci;
1875     byte cai[15];
1876   dword d;
1877     API_PARSE dummy;
1878
1879   dbug(1,dprintf("facility_req"));
1880   for(i=0;i<9;i++) ss_parms[i].length = 0;
1881
1882   parms = &msg[1];
1883
1884   if(!a)
1885   {
1886     dbug(1,dprintf("wrong Ctrl"));
1887     Info = _WRONG_IDENTIFIER;
1888   }
1889
1890   selector = GET_WORD(msg[0].info);
1891
1892   if(!Info)
1893   {
1894     switch(selector)
1895     {
1896       case SELECTOR_HANDSET:
1897         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1898         break;
1899
1900       case SELECTOR_SU_SERV:
1901         if(!msg[1].length)
1902         {
1903           Info = _WRONG_MESSAGE_FORMAT;
1904           break;
1905         }
1906         SSreq = GET_WORD(&(msg[1].info[1]));
1907         PUT_WORD(&RCparms[1],SSreq);
1908         SSparms = RCparms;
1909         switch(SSreq)
1910         {
1911           case S_GET_SUPPORTED_SERVICES:
1912             if((i=get_plci(a)))
1913             {
1914               rplci = &a->plci[i-1];
1915               rplci->appl = appl;
1916               add_p(rplci,CAI,"\x01\x80");
1917               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1918               sig_req(rplci,ASSIGN,DSIG_ID);
1919               send_req(rplci);
1920             }
1921             else
1922             {
1923               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1924               SSparms = (byte *)SSstruct;
1925               break;
1926             }
1927             rplci->internal_command = GETSERV_REQ_PEND;
1928             rplci->number = Number;
1929             rplci->appl = appl;
1930             sig_req(rplci,S_SUPPORTED,0);
1931             send_req(rplci);
1932             return false;
1933             break;
1934
1935           case S_LISTEN:
1936             if(parms->length==7)
1937             {
1938               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1939               {
1940                 dbug(1,dprintf("format wrong"));
1941                 Info = _WRONG_MESSAGE_FORMAT;
1942                 break;
1943               }
1944             }
1945             else
1946             {
1947               Info = _WRONG_MESSAGE_FORMAT;
1948               break;
1949             }
1950             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1951             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1952             {
1953               if((i=get_plci(a)))
1954               {
1955                 rplci = &a->plci[i-1];
1956                 rplci->appl = appl;
1957                 add_p(rplci,CAI,"\x01\x80");
1958                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1959                 sig_req(rplci,ASSIGN,DSIG_ID);
1960                 send_req(rplci);
1961               }
1962               else
1963               {
1964                 break;
1965               }
1966               rplci->internal_command = GET_MWI_STATE;
1967               rplci->number = Number;
1968               sig_req(rplci,MWI_POLL,0);
1969               send_req(rplci);
1970             }
1971             break;
1972
1973           case S_HOLD:
1974             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1975             if(plci && plci->State && plci->SuppState==IDLE)
1976             {
1977               plci->SuppState = HOLD_REQUEST;
1978               plci->command = C_HOLD_REQ;
1979               add_s(plci,CAI,&ss_parms[1]);
1980               sig_req(plci,CALL_HOLD,0);
1981               send_req(plci);
1982               return false;
1983             }
1984             else Info = 0x3010;                    /* wrong state           */
1985             break;
1986           case S_RETRIEVE:
1987             if(plci && plci->State && plci->SuppState==CALL_HELD)
1988             {
1989               if(Id & EXT_CONTROLLER)
1990               {
1991                 if(AdvCodecSupport(a, plci, appl, 0))
1992                 {
1993                   Info = 0x3010;                    /* wrong state           */
1994                   break;
1995                 }
1996               }
1997               else plci->tel = 0;
1998
1999               plci->SuppState = RETRIEVE_REQUEST;
2000               plci->command = C_RETRIEVE_REQ;
2001               if(plci->spoofed_msg==SPOOFING_REQUIRED)
2002               {
2003                 plci->spoofed_msg = CALL_RETRIEVE;
2004                 plci->internal_command = BLOCK_PLCI;
2005                 plci->command = 0;
2006                 dbug(1,dprintf("Spoof"));
2007                 return false;
2008               }
2009               else
2010               {
2011                 sig_req(plci,CALL_RETRIEVE,0);
2012                 send_req(plci);
2013                 return false;
2014               }
2015             }
2016             else Info = 0x3010;                    /* wrong state           */
2017             break;
2018           case S_SUSPEND:
2019             if(parms->length)
2020             {
2021               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2022               {
2023                 dbug(1,dprintf("format wrong"));
2024                 Info = _WRONG_MESSAGE_FORMAT;
2025                 break;
2026               }
2027             }
2028             if(plci && plci->State)
2029             {
2030               add_s(plci,CAI,&ss_parms[2]);
2031               plci->command = SUSPEND_REQ;
2032               sig_req(plci,SUSPEND,0);
2033               plci->State = SUSPENDING;
2034               send_req(plci);
2035             }
2036             else Info = 0x3010;                    /* wrong state           */
2037             break;
2038
2039           case S_RESUME:
2040             if(!(i=get_plci(a)) )
2041             {
2042               Info = _OUT_OF_PLCI;
2043               break;
2044             }
2045             rplci = &a->plci[i-1];
2046             rplci->appl = appl;
2047             rplci->number = Number;
2048             rplci->tel = 0;
2049             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2050             /* check 'external controller' bit for codec support */
2051             if(Id & EXT_CONTROLLER)
2052             {
2053               if(AdvCodecSupport(a, rplci, appl, 0) )
2054               {
2055                 rplci->Id = 0;
2056                 Info = 0x300A;
2057                 break;
2058               }
2059             }
2060             if(parms->length)
2061             {
2062               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2063               {
2064                 dbug(1,dprintf("format wrong"));
2065                 rplci->Id = 0;
2066                 Info = _WRONG_MESSAGE_FORMAT;
2067                 break;
2068               }
2069             }
2070             dummy.length = 0;
2071             dummy.info = "\x00";
2072             add_b1(rplci, &dummy, 0, 0);
2073             if (a->Info_Mask[appl->Id-1] & 0x200)
2074             {
2075               /* early B3 connect (CIP mask bit 9) no release after a disc */
2076               add_p(rplci,LLI,"\x01\x01");
2077             }
2078             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2079             sig_req(rplci,ASSIGN,DSIG_ID);
2080             send_req(rplci);
2081             add_s(rplci,CAI,&ss_parms[2]);
2082             rplci->command = RESUME_REQ;
2083             sig_req(rplci,RESUME,0);
2084             rplci->State = RESUMING;
2085             send_req(rplci);
2086             break;
2087
2088           case S_CONF_BEGIN: /* Request */
2089           case S_CONF_DROP:
2090           case S_CONF_ISOLATE:
2091           case S_CONF_REATTACH:
2092             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2093             {
2094               dbug(1,dprintf("format wrong"));
2095               Info = _WRONG_MESSAGE_FORMAT;
2096               break;
2097             }
2098             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2099             {
2100               d = GET_DWORD(ss_parms[2].info);     
2101               if(d>=0x80)
2102               {
2103                 dbug(1,dprintf("format wrong"));
2104                 Info = _WRONG_MESSAGE_FORMAT;
2105                 break;
2106               }
2107               plci->ptyState = (byte)SSreq;
2108               plci->command = 0;
2109               cai[0] = 2;
2110               switch(SSreq)
2111               {
2112               case S_CONF_BEGIN:
2113                   cai[1] = CONF_BEGIN;
2114                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2115                   break;
2116               case S_CONF_DROP:
2117                   cai[1] = CONF_DROP;
2118                   plci->internal_command = CONF_DROP_REQ_PEND;
2119                   break;
2120               case S_CONF_ISOLATE:
2121                   cai[1] = CONF_ISOLATE;
2122                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2123                   break;
2124               case S_CONF_REATTACH:
2125                   cai[1] = CONF_REATTACH;
2126                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2127                   break;
2128               }
2129               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2130               add_p(plci,CAI,cai);
2131               sig_req(plci,S_SERVICE,0);
2132               send_req(plci);
2133               return false;
2134             }
2135             else Info = 0x3010;                    /* wrong state           */
2136             break;
2137
2138           case S_ECT:
2139           case S_3PTY_BEGIN:
2140           case S_3PTY_END:
2141           case S_CONF_ADD:
2142             if(parms->length==7)
2143             {
2144               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2145               {
2146                 dbug(1,dprintf("format wrong"));
2147                 Info = _WRONG_MESSAGE_FORMAT;
2148                 break;
2149               }
2150             }
2151             else if(parms->length==8) /* workaround for the T-View-S */
2152             {
2153               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2154               {
2155                 dbug(1,dprintf("format wrong"));
2156                 Info = _WRONG_MESSAGE_FORMAT;
2157                 break;
2158               }
2159             }
2160             else
2161             {
2162               Info = _WRONG_MESSAGE_FORMAT;
2163               break;
2164             }
2165             if(!msg[1].length)
2166             {
2167               Info = _WRONG_MESSAGE_FORMAT;
2168               break;
2169             }
2170             if (!plci)
2171             {
2172               Info = _WRONG_IDENTIFIER;
2173               break;
2174             }
2175             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2176             relatedPLCIvalue &= 0x0000FFFF;
2177             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2178             /* controller starts with 0 up to (max_adapter - 1) */
2179             if (((relatedPLCIvalue & 0x7f) == 0)
2180              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2181              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2182             {
2183               if(SSreq==S_3PTY_END)
2184               {
2185                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2186                 rplci = plci;
2187               }
2188               else
2189               {
2190                 Info = 0x3010;                    /* wrong state           */
2191                 break;
2192               }
2193             }
2194             else
2195             {  
2196               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2197               relatedPLCIvalue >>=8;
2198               /* find PLCI PTR*/
2199               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2200               {
2201                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2202                 {
2203                   rplci = &relatedadapter->plci[i];
2204                 }
2205               }
2206               if(!rplci || !relatedPLCIvalue)
2207               {
2208                 if(SSreq==S_3PTY_END)
2209                 {
2210                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2211                   rplci = plci;
2212                 }
2213                 else
2214                 {
2215                   Info = 0x3010;                    /* wrong state           */
2216                   break;
2217                 }
2218               }
2219             }
2220 /*
2221             dbug(1,dprintf("rplci:%x",rplci));
2222             dbug(1,dprintf("plci:%x",plci));
2223             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2224             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2225             dbug(1,dprintf("SSreq:%x",SSreq));
2226             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2227             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2228             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2229 */
2230             /* send PTY/ECT req, cannot check all states because of US stuff */
2231             if( !rplci->internal_command && rplci->appl )
2232             {
2233               plci->command = 0;
2234               rplci->relatedPTYPLCI = plci;
2235               plci->relatedPTYPLCI = rplci;
2236               rplci->ptyState = (byte)SSreq;
2237               if(SSreq==S_ECT)
2238               {
2239                 rplci->internal_command = ECT_REQ_PEND;
2240                 cai[1] = ECT_EXECUTE;
2241
2242                 rplci->vswitchstate=0;
2243                 rplci->vsprot=0;
2244                 rplci->vsprotdialect=0;
2245                 plci->vswitchstate=0;
2246                 plci->vsprot=0;
2247                 plci->vsprotdialect=0;
2248
2249               }
2250               else if(SSreq==S_CONF_ADD)
2251               {
2252                 rplci->internal_command = CONF_ADD_REQ_PEND;
2253                 cai[1] = CONF_ADD;
2254               }
2255               else
2256               {
2257                 rplci->internal_command = PTY_REQ_PEND;
2258                 cai[1] = (byte)(SSreq-3);
2259               }
2260               rplci->number = Number;
2261               if(plci!=rplci) /* explicit invocation */
2262               {
2263                 cai[0] = 2;
2264                 cai[2] = plci->Sig.Id;
2265                 dbug(1,dprintf("explicit invocation"));
2266               }
2267               else
2268               {
2269                 dbug(1,dprintf("implicit invocation"));
2270                 cai[0] = 1;
2271               }
2272               add_p(rplci,CAI,cai);
2273               sig_req(rplci,S_SERVICE,0);
2274               send_req(rplci);
2275               return false;
2276             }
2277             else
2278             {
2279               dbug(0,dprintf("Wrong line"));
2280               Info = 0x3010;                    /* wrong state           */
2281               break;
2282             }
2283             break;
2284
2285           case S_CALL_DEFLECTION:
2286             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2287             {
2288               dbug(1,dprintf("format wrong"));
2289               Info = _WRONG_MESSAGE_FORMAT;
2290               break;
2291             }
2292             if (!plci)
2293             {
2294               Info = _WRONG_IDENTIFIER;
2295               break;
2296             }
2297             /* reuse unused screening indicator */
2298             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2299             plci->command = 0;
2300             plci->internal_command = CD_REQ_PEND;
2301             appl->CDEnable = true;
2302             cai[0] = 1;
2303             cai[1] = CALL_DEFLECTION;
2304             add_p(plci,CAI,cai);
2305             add_p(plci,CPN,ss_parms[3].info);
2306             sig_req(plci,S_SERVICE,0);
2307             send_req(plci);
2308             return false;
2309             break;
2310
2311           case S_CALL_FORWARDING_START:
2312             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2313             {
2314               dbug(1,dprintf("format wrong"));
2315               Info = _WRONG_MESSAGE_FORMAT;
2316               break;
2317             }
2318
2319             if((i=get_plci(a)))
2320             {
2321               rplci = &a->plci[i-1];
2322               rplci->appl = appl;
2323               add_p(rplci,CAI,"\x01\x80");
2324               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2325               sig_req(rplci,ASSIGN,DSIG_ID);
2326               send_req(rplci);
2327             }
2328             else
2329             {
2330               Info = _OUT_OF_PLCI;
2331               break;
2332             }
2333
2334             /* reuse unused screening indicator */
2335             rplci->internal_command = CF_START_PEND;
2336             rplci->appl = appl;
2337             rplci->number = Number;
2338             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2339             cai[0] = 2;
2340             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2341             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2342             add_p(rplci,CAI,cai);
2343             add_p(rplci,OAD,ss_parms[5].info);
2344             add_p(rplci,CPN,ss_parms[6].info);
2345             sig_req(rplci,S_SERVICE,0);
2346             send_req(rplci);
2347             return false;
2348             break;
2349
2350           case S_INTERROGATE_DIVERSION:
2351           case S_INTERROGATE_NUMBERS:
2352           case S_CALL_FORWARDING_STOP:
2353           case S_CCBS_REQUEST:
2354           case S_CCBS_DEACTIVATE:
2355           case S_CCBS_INTERROGATE:
2356             switch(SSreq)
2357             {
2358             case S_INTERROGATE_NUMBERS:
2359                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2360                 {
2361                   dbug(0,dprintf("format wrong"));
2362                   Info = _WRONG_MESSAGE_FORMAT;
2363                 }
2364                 break;
2365             case S_CCBS_REQUEST:
2366             case S_CCBS_DEACTIVATE:
2367                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2368                 {
2369                   dbug(0,dprintf("format wrong"));
2370                   Info = _WRONG_MESSAGE_FORMAT;
2371                 }
2372                 break;
2373             case S_CCBS_INTERROGATE:
2374                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2375                 {
2376                   dbug(0,dprintf("format wrong"));
2377                   Info = _WRONG_MESSAGE_FORMAT;
2378                 }
2379                 break;
2380             default:
2381             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2382             {
2383               dbug(0,dprintf("format wrong"));
2384               Info = _WRONG_MESSAGE_FORMAT;
2385               break;
2386             }
2387                 break;
2388             }
2389
2390             if(Info) break;
2391             if((i=get_plci(a)))
2392             {
2393               rplci = &a->plci[i-1];
2394               switch(SSreq)
2395               {
2396                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2397                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2398                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2399                   break;
2400                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2401                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2402                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2403                   break;
2404                 case S_CALL_FORWARDING_STOP:
2405                   rplci->internal_command = CF_STOP_PEND;
2406                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2407                   break;
2408                 case S_CCBS_REQUEST:
2409                   cai[1] = CCBS_REQUEST;
2410                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2411                   break;
2412                 case S_CCBS_DEACTIVATE:
2413                   cai[1] = CCBS_DEACTIVATE;
2414                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2415                   break;
2416                 case S_CCBS_INTERROGATE:
2417                   cai[1] = CCBS_INTERROGATE;
2418                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2419                   break;
2420                 default:
2421                   cai[1] = 0;
2422                 break;
2423               }
2424               rplci->appl = appl;
2425               rplci->number = Number;
2426               add_p(rplci,CAI,"\x01\x80");
2427               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2428               sig_req(rplci,ASSIGN,DSIG_ID);
2429               send_req(rplci);
2430             }
2431             else
2432             {
2433               Info = _OUT_OF_PLCI;
2434               break;
2435             }
2436
2437             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2438             switch(SSreq)
2439             {
2440             case S_INTERROGATE_NUMBERS:
2441                 cai[0] = 1;
2442                 add_p(rplci,CAI,cai);
2443                 break;
2444             case S_CCBS_REQUEST:
2445             case S_CCBS_DEACTIVATE:
2446                 cai[0] = 3;
2447                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2448                 add_p(rplci,CAI,cai);
2449                 break;
2450             case S_CCBS_INTERROGATE:
2451                 cai[0] = 3;
2452                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2453                 add_p(rplci,CAI,cai);
2454                 add_p(rplci,OAD,ss_parms[4].info);
2455                 break;
2456             default:
2457             cai[0] = 2;
2458             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2459             add_p(rplci,CAI,cai);
2460             add_p(rplci,OAD,ss_parms[5].info);
2461                 break;
2462             }
2463                         
2464             sig_req(rplci,S_SERVICE,0);
2465             send_req(rplci);
2466             return false;
2467             break;
2468
2469           case S_MWI_ACTIVATE:
2470             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2471             {
2472               dbug(1,dprintf("format wrong"));
2473               Info = _WRONG_MESSAGE_FORMAT;
2474               break;
2475             }
2476             if(!plci)
2477             {                               
2478               if((i=get_plci(a)))
2479               {
2480                 rplci = &a->plci[i-1];
2481                 rplci->appl = appl;
2482                 rplci->cr_enquiry=true;
2483                 add_p(rplci,CAI,"\x01\x80");
2484                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2485                 sig_req(rplci,ASSIGN,DSIG_ID);
2486                 send_req(rplci);
2487               }
2488               else
2489               {
2490                 Info = _OUT_OF_PLCI;
2491                 break;
2492               }
2493             }
2494             else
2495             {
2496               rplci = plci;
2497               rplci->cr_enquiry=false;
2498             }
2499
2500             rplci->command = 0;
2501             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2502             rplci->appl = appl;
2503             rplci->number = Number;
2504
2505             cai[0] = 13;
2506             cai[1] = ACTIVATION_MWI; /* Function */
2507             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2508             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2509             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2510             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2511             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2512             add_p(rplci,CAI,cai);
2513             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2514             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2515             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2516             add_p(rplci,UID,ss_parms[10].info); /* Time */
2517             sig_req(rplci,S_SERVICE,0);
2518             send_req(rplci);
2519             return false;
2520
2521           case S_MWI_DEACTIVATE:
2522             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2523             {
2524               dbug(1,dprintf("format wrong"));
2525               Info = _WRONG_MESSAGE_FORMAT;
2526               break;
2527             }
2528             if(!plci)
2529             {                               
2530               if((i=get_plci(a)))
2531               {
2532                 rplci = &a->plci[i-1];
2533                 rplci->appl = appl;
2534                 rplci->cr_enquiry=true;
2535                 add_p(rplci,CAI,"\x01\x80");
2536                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2537                 sig_req(rplci,ASSIGN,DSIG_ID);
2538                 send_req(rplci);
2539               }
2540               else
2541               {
2542                 Info = _OUT_OF_PLCI;
2543                 break;
2544               }
2545             }
2546             else
2547             {
2548               rplci = plci;
2549               rplci->cr_enquiry=false;
2550             }
2551
2552             rplci->command = 0;
2553             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2554             rplci->appl = appl;
2555             rplci->number = Number;
2556
2557             cai[0] = 5;
2558             cai[1] = DEACTIVATION_MWI; /* Function */
2559             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2560             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2561             add_p(rplci,CAI,cai);
2562             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2563             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2564             sig_req(rplci,S_SERVICE,0);
2565             send_req(rplci);
2566             return false;
2567
2568           default:
2569             Info = 0x300E;  /* not supported */
2570             break;
2571         }
2572         break; /* case SELECTOR_SU_SERV: end */
2573
2574
2575       case SELECTOR_DTMF:
2576         return (dtmf_request (Id, Number, a, plci, appl, msg));
2577
2578
2579
2580       case SELECTOR_LINE_INTERCONNECT:
2581         return (mixer_request (Id, Number, a, plci, appl, msg));
2582
2583
2584
2585       case PRIV_SELECTOR_ECHO_CANCELLER:
2586         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2587         return (ec_request (Id, Number, a, plci, appl, msg));
2588
2589       case SELECTOR_ECHO_CANCELLER:
2590         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2591         return (ec_request (Id, Number, a, plci, appl, msg));
2592
2593
2594       case SELECTOR_V42BIS:
2595       default:
2596         Info = _FACILITY_NOT_SUPPORTED;
2597         break;
2598     } /* end of switch(selector) */
2599   }
2600
2601   dbug(1,dprintf("SendFacRc"));
2602   sendf(appl,
2603         _FACILITY_R|CONFIRM,
2604         Id,
2605         Number,
2606         "wws",Info,selector,SSparms);
2607   return false;
2608 }
2609
2610 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2611                          PLCI *plci, APPL *appl, API_PARSE *msg)
2612 {
2613   dbug(1,dprintf("facility_res"));
2614   return false;
2615 }
2616
2617 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2618                            PLCI *plci, APPL *appl, API_PARSE *parms)
2619 {
2620   word Info = 0;
2621   byte req;
2622   byte len;
2623   word w;
2624   word fax_control_bits, fax_feature_bits, fax_info_change;
2625   API_PARSE * ncpi;
2626     byte pvc[2];
2627
2628     API_PARSE fax_parms[9];
2629   word i;
2630
2631
2632   dbug(1,dprintf("connect_b3_req"));
2633   if(plci)
2634   {
2635     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2636      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2637     {
2638       Info = _WRONG_STATE;
2639     }
2640     else
2641     {
2642       /* local reply if assign unsuccessful
2643          or B3 protocol allows only one layer 3 connection
2644            and already connected
2645              or B2 protocol not any LAPD
2646                and connect_b3_req contradicts originate/answer direction */
2647       if (!plci->NL.Id
2648        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2649         && ((plci->channels != 0)
2650          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2651           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2652       {
2653         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2654                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2655         Info = _WRONG_STATE;
2656         sendf(appl,                                                        
2657               _CONNECT_B3_R|CONFIRM,
2658               Id,
2659               Number,
2660               "w",Info);
2661         return false;
2662       }
2663       plci->requested_options_conn = 0;
2664
2665       req = N_CONNECT;
2666       ncpi = &parms[0];
2667       if(plci->B3_prot==2 || plci->B3_prot==3)
2668       {
2669         if(ncpi->length>2)
2670         {
2671           /* check for PVC */
2672           if(ncpi->info[2] || ncpi->info[3])
2673           {
2674             pvc[0] = ncpi->info[3];
2675             pvc[1] = ncpi->info[2];
2676             add_d(plci,2,pvc);
2677             req = N_RESET;
2678           }
2679           else
2680           {
2681             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2682             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2683           }
2684         }
2685       }
2686       else if(plci->B3_prot==5)
2687       {
2688         if (plci->NL.Id && !plci->nl_remove_id)
2689         {
2690           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2691           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2692           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2693            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2694           {
2695             len = offsetof(T30_INFO, universal_6);
2696             fax_info_change = false;
2697             if (ncpi->length >= 4)
2698             {
2699               w = GET_WORD(&ncpi->info[3]);
2700               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2701               {
2702                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2703                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2704                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2705                 fax_info_change = true;
2706               }
2707               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2708               if (w & 0x0002)  /* Fax-polling request */
2709                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2710               if ((w & 0x0004) /* Request to send / poll another document */
2711                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2712               {
2713                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2714               }
2715               if (ncpi->length >= 6)
2716               {
2717                 w = GET_WORD(&ncpi->info[5]);
2718                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2719                 {
2720                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2721                   fax_info_change = true;
2722                 }
2723
2724                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2725                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2726                 {
2727                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2728                 }
2729                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2730                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2731                 {
2732                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2733                 }
2734                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2735                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2736                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2737                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2738                 {
2739                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2740                     Info = _WRONG_MESSAGE_FORMAT;
2741                   else
2742                   {
2743                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2744                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2745       {
2746                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2747                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2748                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2749       }
2750                     w = fax_parms[4].length;
2751                     if (w > 20)
2752                       w = 20;
2753                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2754                     for (i = 0; i < w; i++)
2755                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2756                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2757                     len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2758                     w = fax_parms[5].length;
2759                     if (w > 20)
2760                       w = 20;
2761                     plci->fax_connect_info_buffer[len++] = (byte) w;
2762                     for (i = 0; i < w; i++)
2763                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2764                     w = fax_parms[6].length;
2765                     if (w > 20)
2766                       w = 20;
2767                     plci->fax_connect_info_buffer[len++] = (byte) w;
2768                     for (i = 0; i < w; i++)
2769                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2770                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2771                       & (1L << PRIVATE_FAX_NONSTANDARD))
2772       {
2773                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2774         {
2775                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2776                         plci->fax_connect_info_buffer[len++] = 0;
2777         }
2778                       else
2779                       {
2780           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2781             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2782    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2783           for (i = 0; i < fax_parms[7].length; i++)
2784      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2785                       }
2786                     }
2787                   }
2788                 }
2789                 else
2790                 {
2791                   len = offsetof(T30_INFO, universal_6);
2792                 }
2793                 fax_info_change = true;
2794
2795               }
2796               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2797               {
2798                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2799                 fax_info_change = true;
2800               }
2801             }
2802             if (Info == GOOD)
2803             {
2804               plci->fax_connect_info_length = len;
2805               if (fax_info_change)
2806               {
2807                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2808                 {
2809                   start_internal_command (Id, plci, fax_connect_info_command);
2810                   return false;
2811                 }
2812                 else
2813                 {
2814                   start_internal_command (Id, plci, fax_adjust_b23_command);
2815                   return false;
2816                 }
2817               }
2818             }
2819           }
2820           else  Info = _WRONG_STATE;
2821         }
2822         else  Info = _WRONG_STATE;
2823       }
2824
2825       else if (plci->B3_prot == B3_RTP)
2826       {
2827         plci->internal_req_buffer[0] = ncpi->length + 1;
2828         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2829         for (w = 0; w < ncpi->length; w++)
2830           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2831         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2832         return false;
2833       }
2834
2835       if(!Info)
2836       {
2837         nl_req_ncci(plci,req,0);
2838         return 1;
2839       }
2840     }
2841   }
2842   else Info = _WRONG_IDENTIFIER;
2843
2844   sendf(appl,
2845         _CONNECT_B3_R|CONFIRM,
2846         Id,
2847         Number,
2848         "w",Info);
2849   return false;
2850 }
2851
2852 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2853                            PLCI *plci, APPL *appl, API_PARSE *parms)
2854 {
2855   word ncci;
2856   API_PARSE * ncpi;
2857   byte req;
2858
2859   word w;
2860
2861
2862     API_PARSE fax_parms[9];
2863   word i;
2864   byte len;
2865
2866
2867   dbug(1,dprintf("connect_b3_res"));
2868
2869   ncci = (word)(Id>>16);
2870   if(plci && ncci) {
2871     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2872       if (GET_WORD (&parms[0].info[0]) != 0)
2873       {
2874         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2875         channel_request_xon (plci, a->ncci_ch[ncci]);
2876         channel_xmit_xon (plci);
2877         cleanup_ncci_data (plci, ncci);
2878         nl_req_ncci(plci,N_DISC,(byte)ncci);
2879         return 1;
2880       }
2881       a->ncci_state[ncci] = INC_ACT_PENDING;
2882
2883       req = N_CONNECT_ACK;
2884       ncpi = &parms[1];
2885       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2886       {
2887
2888         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2889           & (1L << PRIVATE_FAX_NONSTANDARD))
2890  {
2891    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2892     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2893     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2894    {
2895             len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2896             if (plci->fax_connect_info_length < len)
2897             {
2898               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2899               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2900             }
2901             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2902             {
2903               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2904             }
2905             else
2906             {
2907               if (plci->fax_connect_info_length <= len)
2908                 plci->fax_connect_info_buffer[len] = 0;
2909               len += 1 + plci->fax_connect_info_buffer[len];
2910               if (plci->fax_connect_info_length <= len)
2911                 plci->fax_connect_info_buffer[len] = 0;
2912               len += 1 + plci->fax_connect_info_buffer[len];
2913               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2914                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2915               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2916               for (i = 0; i < fax_parms[7].length; i++)
2917                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2918             }
2919             plci->fax_connect_info_length = len;
2920             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2921             start_internal_command (Id, plci, fax_connect_ack_command);
2922      return false;
2923           }
2924         }
2925
2926         nl_req_ncci(plci,req,(byte)ncci);
2927         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2928          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2929         {
2930           if (plci->B3_prot == 4)
2931             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2932           else
2933             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2934           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2935         }
2936       }
2937
2938       else if (plci->B3_prot == B3_RTP)
2939       {
2940         plci->internal_req_buffer[0] = ncpi->length + 1;
2941         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2942         for (w = 0; w < ncpi->length; w++)
2943           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2944         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2945         return false;
2946       }
2947
2948       else
2949       {
2950         if(ncpi->length>2) {
2951           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2952           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2953         }
2954         nl_req_ncci(plci,req,(byte)ncci);
2955         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2956         if (plci->adjust_b_restore)
2957         {
2958           plci->adjust_b_restore = false;
2959           start_internal_command (Id, plci, adjust_b_restore);
2960         }
2961       }
2962       return 1;
2963     }
2964   }
2965   return false;
2966 }
2967
2968 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2969                              PLCI *plci, APPL *appl, API_PARSE *parms)
2970 {
2971   word ncci;
2972
2973   ncci = (word)(Id>>16);
2974   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2975
2976   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2977    && (plci->State != OUTG_DIS_PENDING))
2978   {
2979     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2980       a->ncci_state[ncci] = CONNECTED;
2981       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2982       channel_request_xon (plci, a->ncci_ch[ncci]);
2983       channel_xmit_xon (plci);
2984     }
2985   }
2986   return false;
2987 }
2988
2989 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2990                               PLCI *plci, APPL *appl, API_PARSE *parms)
2991 {
2992   word Info;
2993   word ncci;
2994   API_PARSE * ncpi;
2995
2996   dbug(1,dprintf("disconnect_b3_req"));
2997
2998   Info = _WRONG_IDENTIFIER;
2999   ncci = (word)(Id>>16);
3000   if (plci && ncci)
3001   {
3002     Info = _WRONG_STATE;
3003     if ((a->ncci_state[ncci] == CONNECTED)
3004      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3005      || (a->ncci_state[ncci] == INC_CON_PENDING)
3006      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3007     {
3008       a->ncci_state[ncci] = OUTG_DIS_PENDING;
3009       channel_request_xon (plci, a->ncci_ch[ncci]);
3010       channel_xmit_xon (plci);
3011
3012       if (a->ncci[ncci].data_pending
3013        && ((plci->B3_prot == B3_TRANSPARENT)
3014         || (plci->B3_prot == B3_T30)
3015         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3016       {
3017         plci->send_disc = (byte)ncci;
3018         plci->command = 0;
3019         return false;
3020       }
3021       else
3022       {
3023         cleanup_ncci_data (plci, ncci);
3024
3025         if(plci->B3_prot==2 || plci->B3_prot==3)
3026         {
3027           ncpi = &parms[0];
3028           if(ncpi->length>3)
3029           {
3030             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3031           }
3032         }
3033         nl_req_ncci(plci,N_DISC,(byte)ncci);
3034       }
3035       return 1;
3036     }
3037   }
3038   sendf(appl,
3039         _DISCONNECT_B3_R|CONFIRM,
3040         Id,
3041         Number,
3042         "w",Info);
3043   return false;
3044 }
3045
3046 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3047                               PLCI *plci, APPL *appl, API_PARSE *parms)
3048 {
3049   word ncci;
3050   word i;
3051
3052   ncci = (word)(Id>>16);
3053   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3054   if(plci && ncci) {
3055     plci->requested_options_conn = 0;
3056     plci->fax_connect_info_length = 0;
3057     plci->ncpi_state = 0x00;
3058     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3059       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3060     {
3061       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3062     }
3063     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3064     if(i<MAX_CHANNELS_PER_PLCI) {
3065       if(plci->channels)plci->channels--;
3066       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3067       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3068
3069       ncci_free_receive_buffers (plci, ncci);
3070
3071       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3072         if(plci->State == SUSPENDING){
3073           sendf(plci->appl,
3074                 _FACILITY_I,
3075                 Id & 0xffffL,
3076                 0,
3077                 "ws", (word)3, "\x03\x04\x00\x00");
3078           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3079         }
3080         plci_remove(plci);
3081         plci->State=IDLE;
3082       }
3083     }
3084     else
3085     {
3086       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3087        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3088        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3089       {
3090         ncci_free_receive_buffers (plci, ncci);
3091
3092         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3093
3094         plci->adapter->ncci_state[ncci] = IDLE;
3095         start_internal_command (Id, plci, fax_disconnect_command);
3096         return 1;
3097       }
3098     }
3099   }
3100   return false;
3101 }
3102
3103 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3104                         PLCI *plci, APPL *appl, API_PARSE *parms)
3105 {
3106   NCCI   *ncci_ptr;
3107   DATA_B3_DESC   *data;
3108   word Info;
3109   word ncci;
3110   word i;
3111
3112   dbug(1,dprintf("data_b3_req"));
3113
3114   Info = _WRONG_IDENTIFIER;
3115   ncci = (word)(Id>>16);
3116   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3117
3118   if (plci && ncci)
3119   {
3120     Info = _WRONG_STATE;
3121     if ((a->ncci_state[ncci] == CONNECTED)
3122      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3123     {
3124         /* queue data */
3125       ncci_ptr = &(a->ncci[ncci]);
3126       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3127       if (i >= MAX_DATA_B3)
3128         i -= MAX_DATA_B3;
3129       data = &(ncci_ptr->DBuffer[i]);
3130       data->Number = Number;
3131       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3132        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3133       {
3134
3135         data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3136
3137       }
3138       else
3139         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3140       data->Length = GET_WORD(parms[1].info);
3141       data->Handle = GET_WORD(parms[2].info);
3142       data->Flags = GET_WORD(parms[3].info);
3143       (ncci_ptr->data_pending)++;
3144
3145         /* check for delivery confirmation */
3146       if (data->Flags & 0x0004)
3147       {
3148         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3149         if (i >= MAX_DATA_ACK)
3150           i -= MAX_DATA_ACK;
3151         ncci_ptr->DataAck[i].Number = data->Number;
3152         ncci_ptr->DataAck[i].Handle = data->Handle;
3153         (ncci_ptr->data_ack_pending)++;
3154       }
3155
3156       send_data(plci);
3157       return false;
3158     }
3159   }
3160   if (appl)
3161   {
3162     if (plci)
3163     {
3164       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3165        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3166       {
3167
3168         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3169
3170       }
3171     }
3172     sendf(appl,
3173           _DATA_B3_R|CONFIRM,
3174           Id,
3175           Number,
3176           "ww",GET_WORD(parms[2].info),Info);
3177   }
3178   return false;
3179 }
3180
3181 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3182                         PLCI *plci, APPL *appl, API_PARSE *parms)
3183 {
3184   word n;
3185   word ncci;
3186   word NCCIcode;
3187
3188   dbug(1,dprintf("data_b3_res"));
3189
3190   ncci = (word)(Id>>16);
3191   if(plci && ncci) {
3192     n = GET_WORD(parms[0].info);
3193     dbug(1,dprintf("free(%d)",n));
3194     NCCIcode = ncci | (((word) a->Id) << 8);
3195     if(n<appl->MaxBuffer &&
3196        appl->DataNCCI[n]==NCCIcode &&
3197        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3198       dbug(1,dprintf("found"));
3199       appl->DataNCCI[n] = 0;
3200
3201       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3202         channel_request_xon (plci, a->ncci_ch[ncci]);
3203       }
3204       channel_xmit_xon (plci);
3205
3206       if(appl->DataFlags[n] &4) {
3207         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3208         return 1;
3209       }
3210     }
3211   }
3212   return false;
3213 }
3214
3215 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3216                          PLCI *plci, APPL *appl, API_PARSE *parms)
3217 {
3218   word Info;
3219   word ncci;
3220
3221   dbug(1,dprintf("reset_b3_req"));
3222
3223   Info = _WRONG_IDENTIFIER;
3224   ncci = (word)(Id>>16);
3225   if(plci && ncci)
3226   {
3227     Info = _WRONG_STATE;
3228     switch (plci->B3_prot)
3229     {
3230     case B3_ISO8208:
3231     case B3_X25_DCE:
3232       if(a->ncci_state[ncci]==CONNECTED)
3233       {
3234         nl_req_ncci(plci,N_RESET,(byte)ncci);
3235         send_req(plci);
3236         Info = GOOD;
3237       }
3238       break;
3239     case B3_TRANSPARENT:
3240       if(a->ncci_state[ncci]==CONNECTED)
3241       {
3242         start_internal_command (Id, plci, reset_b3_command);
3243         Info = GOOD;
3244       }
3245       break;
3246     }
3247   }
3248   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3249   sendf(appl,
3250         _RESET_B3_R|CONFIRM,
3251         Id,
3252         Number,
3253         "w",Info);
3254   return false;
3255 }
3256
3257 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3258                          PLCI *plci, APPL *appl, API_PARSE *parms)
3259 {
3260   word ncci;
3261
3262   dbug(1,dprintf("reset_b3_res"));
3263
3264   ncci = (word)(Id>>16);
3265   if(plci && ncci) {
3266     switch (plci->B3_prot)
3267     {
3268     case B3_ISO8208:
3269     case B3_X25_DCE:
3270       if(a->ncci_state[ncci]==INC_RES_PENDING)
3271       {
3272         a->ncci_state[ncci] = CONNECTED;
3273         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3274         return true;
3275       }
3276     break;
3277     }
3278   }
3279   return false;
3280 }
3281
3282 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3283                                  PLCI *plci, APPL *appl, API_PARSE *parms)
3284 {
3285   word ncci;
3286   API_PARSE * ncpi;
3287   byte req;
3288
3289   dbug(1,dprintf("connect_b3_t90_a_res"));
3290
3291   ncci = (word)(Id>>16);
3292   if(plci && ncci) {
3293     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3294       a->ncci_state[ncci] = CONNECTED;
3295     }
3296     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3297       a->ncci_state[ncci] = CONNECTED;
3298
3299       req = N_CONNECT_ACK;
3300
3301         /* parms[0]==0 for CAPI original message definition! */
3302       if(parms[0].info) {
3303         ncpi = &parms[1];
3304         if(ncpi->length>2) {
3305           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3306           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3307         }
3308       }
3309       nl_req_ncci(plci,req,(byte)ncci);
3310       return 1;
3311     }
3312   }
3313   return false;
3314 }
3315
3316
3317 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3318                          PLCI *plci, APPL *appl, API_PARSE *msg)
3319 {
3320   word Info=0;
3321   word i;
3322   byte tel;
3323     API_PARSE bp_parms[7];
3324
3325   if(!plci || !msg)
3326   {
3327     Info = _WRONG_IDENTIFIER;
3328   }
3329   else
3330   {
3331     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3332                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3333     dbug(1,dprintf("PlciState=0x%x",plci->State));
3334     for(i=0;i<7;i++) bp_parms[i].length = 0;
3335
3336     /* check if no channel is open, no B3 connected only */
3337     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3338      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3339     {
3340       Info = _WRONG_STATE;
3341     }
3342     /* check message format and fill bp_parms pointer */
3343     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3344     {
3345       Info = _WRONG_MESSAGE_FORMAT;
3346     }
3347     else
3348     {
3349       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3350       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3351         if(Id & EXT_CONTROLLER)
3352         {
3353           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3354           return 0;
3355         }
3356         plci->State=INC_CON_CONNECTED_ALERT;
3357         plci->appl = appl;
3358         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3359         dump_c_ind_mask (plci);
3360         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3361         {                         /* its quasi a connect        */
3362           if(test_c_ind_mask_bit (plci, i))
3363             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3364         }
3365       }
3366
3367       api_save_msg(msg, "s", &plci->saved_msg);
3368       tel = plci->tel;
3369       if(Id & EXT_CONTROLLER)
3370       {
3371         if(tel) /* external controller in use by this PLCI */
3372         {
3373           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3374           {
3375             dbug(1,dprintf("Ext_Ctrl in use 1"));
3376             Info = _WRONG_STATE;
3377           }
3378         }
3379         else  /* external controller NOT in use by this PLCI ? */
3380         {
3381           if(a->AdvSignalPLCI)
3382           {
3383             dbug(1,dprintf("Ext_Ctrl in use 2"));
3384             Info = _WRONG_STATE;
3385           }
3386           else /* activate the codec */
3387           {
3388             dbug(1,dprintf("Ext_Ctrl start"));
3389             if(AdvCodecSupport(a, plci, appl, 0) )
3390             {
3391               dbug(1,dprintf("Error in codec procedures"));
3392               Info = _WRONG_STATE;
3393             }
3394             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3395             {
3396               plci->spoofed_msg = AWAITING_SELECT_B;
3397               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3398               plci->command = 0;
3399               dbug(1,dprintf("continue if codec loaded"));
3400               return false;
3401             }
3402           }
3403         }
3404       }
3405       else /* external controller bit is OFF */
3406       {
3407         if(tel) /* external controller in use, need to switch off */
3408         {
3409           if(a->AdvSignalAppl==appl)
3410           {
3411             CodecIdCheck(a, plci);
3412             plci->tel = 0;
3413             plci->adv_nl = 0;
3414             dbug(1,dprintf("Ext_Ctrl disable"));
3415           }
3416           else
3417           {
3418             dbug(1,dprintf("Ext_Ctrl not requested"));
3419           }
3420         }
3421       }
3422       if (!Info)
3423       {
3424         if (plci->call_dir & CALL_DIR_OUT)
3425           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3426         else if (plci->call_dir & CALL_DIR_IN)
3427           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3428         start_internal_command (Id, plci, select_b_command);
3429         return false;
3430       }
3431     }
3432   }
3433   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3434   return false;
3435 }
3436
3437 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3438                              PLCI *plci, APPL *appl, API_PARSE *parms)
3439 {
3440   word command;
3441   word i;
3442   word ncci;
3443   API_PARSE * m;
3444     API_PARSE m_parms[5];
3445   word codec;
3446   byte req;
3447   byte ch;
3448   byte dir;
3449   static byte chi[2] = {0x01,0x00};
3450   static byte lli[2] = {0x01,0x00};
3451   static byte codec_cai[2] = {0x01,0x01};
3452   static byte null_msg = {0};
3453   static API_PARSE null_parms = { 0, &null_msg };
3454   PLCI   * v_plci;
3455   word Info=0;
3456
3457   dbug(1,dprintf("manufacturer_req"));
3458   for(i=0;i<5;i++) m_parms[i].length = 0;
3459
3460   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3461     Info = _WRONG_MESSAGE_FORMAT;
3462   }
3463   command = GET_WORD(parms[1].info);
3464   m = &parms[2];
3465   if (!Info)
3466   {
3467     switch(command) {
3468     case _DI_ASSIGN_PLCI:
3469       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3470         Info = _WRONG_MESSAGE_FORMAT;
3471         break;
3472       }
3473       codec = GET_WORD(m_parms[0].info);
3474       ch = m_parms[1].info[0];
3475       dir = m_parms[2].info[0];
3476       if((i=get_plci(a))) {
3477         plci = &a->plci[i-1];
3478         plci->appl = appl;
3479         plci->command = _MANUFACTURER_R;
3480         plci->m_command = command;
3481         plci->number = Number;
3482         plci->State = LOCAL_CONNECT;
3483         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3484         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3485
3486         if((ch==1 || ch==2) && (dir<=2)) {
3487           chi[1] = (byte)(0x80|ch);
3488           lli[1] = 0;
3489           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3490           switch(codec)
3491           {
3492           case 0:
3493             Info = add_b1(plci,&m_parms[3],0,0);
3494             break;
3495           case 1:
3496             add_p(plci,CAI,codec_cai);
3497             break;
3498           /* manual 'swich on' to the codec support without signalling */
3499           /* first 'assign plci' with this function, then use */
3500           case 2:
3501             if(AdvCodecSupport(a, plci, appl, 0) ) {
3502               Info = _RESOURCE_ERROR;
3503             }
3504             else {
3505               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3506               lli[1] = 0x10; /* local call codec stream */
3507             }
3508             break;
3509           }
3510
3511           plci->State = LOCAL_CONNECT;
3512           plci->manufacturer = true;
3513           plci->command = _MANUFACTURER_R;
3514           plci->m_command = command;
3515           plci->number = Number;
3516
3517           if(!Info)
3518           {
3519             add_p(plci,LLI,lli);
3520             add_p(plci,CHI,chi);
3521             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3522             sig_req(plci,ASSIGN,DSIG_ID);
3523
3524             if(!codec)
3525             {
3526               Info = add_b23(plci,&m_parms[3]);
3527               if(!Info)
3528               {
3529                 nl_req_ncci(plci,ASSIGN,0);
3530                 send_req(plci);
3531               }
3532             }
3533             if(!Info)
3534             {
3535               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3536               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3537               {
3538                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3539                 plci->spoofed_msg = AWAITING_MANUF_CON;
3540                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3541                 plci->command = 0;
3542                 send_req(plci);
3543                 return false;
3544               }
3545               if(dir==1) {
3546                 sig_req(plci,CALL_REQ,0);
3547               }
3548               else if(!dir){
3549                 sig_req(plci,LISTEN_REQ,0);
3550               }
3551               send_req(plci);
3552             }
3553             else
3554             {
3555               sendf(appl,
3556                     _MANUFACTURER_R|CONFIRM,
3557                     Id,
3558                     Number,
3559                     "dww",_DI_MANU_ID,command,Info);
3560               return 2;
3561             }
3562           }
3563         }
3564       }
3565       else  Info = _OUT_OF_PLCI;
3566       break;
3567
3568     case _DI_IDI_CTRL:
3569       if(!plci)
3570       {
3571         Info = _WRONG_IDENTIFIER;
3572         break;
3573       }
3574       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3575         Info = _WRONG_MESSAGE_FORMAT;
3576         break;
3577       }
3578       req = m_parms[0].info[0];
3579       plci->command = _MANUFACTURER_R;
3580       plci->m_command = command;
3581       plci->number = Number;
3582       if(req==CALL_REQ)
3583       {
3584         plci->b_channel = getChannel(&m_parms[1]);
3585         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3586         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3587         {
3588           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3589           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3590           plci->command = 0;
3591           break;
3592         }
3593       }
3594       else if(req==LAW_REQ)
3595       {
3596         plci->cr_enquiry = true;
3597       }
3598       add_ss(plci,FTY,&m_parms[1]);
3599       sig_req(plci,req,0);
3600       send_req(plci);
3601       if(req==HANGUP)
3602       {      
3603         if (plci->NL.Id && !plci->nl_remove_id)
3604         {
3605           if (plci->channels)
3606           {
3607             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3608             {
3609               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3610               {
3611                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3612                 cleanup_ncci_data (plci, ncci);
3613                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3614               }
3615             }
3616           }
3617           mixer_remove (plci);
3618           nl_req_ncci(plci,REMOVE,0);
3619           send_req(plci);
3620         }  
3621       }
3622       break;
3623
3624     case _DI_SIG_CTRL:
3625     /* signalling control for loop activation B-channel */
3626       if(!plci)
3627       {
3628         Info = _WRONG_IDENTIFIER;
3629         break;
3630       }
3631       if(m->length){
3632         plci->command = _MANUFACTURER_R;
3633         plci->number = Number;
3634         add_ss(plci,FTY,m);
3635         sig_req(plci,SIG_CTRL,0);
3636         send_req(plci);
3637       }
3638       else Info = _WRONG_MESSAGE_FORMAT;
3639       break;
3640
3641     case _DI_RXT_CTRL:
3642     /* activation control for receiver/transmitter B-channel */
3643       if(!plci)
3644       {
3645         Info = _WRONG_IDENTIFIER;
3646         break;
3647       }
3648       if(m->length){
3649         plci->command = _MANUFACTURER_R;
3650         plci->number = Number;
3651         add_ss(plci,FTY,m);
3652         sig_req(plci,DSP_CTRL,0);
3653         send_req(plci);
3654       }
3655       else Info = _WRONG_MESSAGE_FORMAT;
3656       break;
3657
3658     case _DI_ADV_CODEC:
3659     case _DI_DSP_CTRL:
3660       /* TEL_CTRL commands to support non standard adjustments: */
3661       /* Ring on/off, Handset micro volume, external micro vol. */
3662       /* handset+external speaker volume, receiver+transm. gain,*/
3663       /* handsfree on (hookinfo off), set mixer command         */
3664
3665       if(command == _DI_ADV_CODEC)
3666       {
3667         if(!a->AdvCodecPLCI) {
3668           Info = _WRONG_STATE;
3669           break;
3670         }
3671         v_plci = a->AdvCodecPLCI;
3672       }
3673       else
3674       {
3675         if (plci
3676          && (m->length >= 3)
3677          && (m->info[1] == 0x1c)
3678          && (m->info[2] >= 1))
3679         {
3680           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3681           {
3682             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3683             {
3684               Info = _WRONG_STATE;
3685               break;
3686             }
3687             a->adv_voice_coef_length = m->info[2] - 1;
3688             if (a->adv_voice_coef_length > m->length - 3)
3689               a->adv_voice_coef_length = (byte)(m->length - 3);
3690             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3691               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3692             for (i = 0; i < a->adv_voice_coef_length; i++)
3693               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3694             if (plci->B1_facilities & B1_FACILITY_VOICE)
3695               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3696             break;
3697           }
3698           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3699           {
3700             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3701             {
3702               Info = _FACILITY_NOT_SUPPORTED;
3703               break;
3704             }
3705
3706             plci->dtmf_parameter_length = m->info[2] - 1;
3707             if (plci->dtmf_parameter_length > m->length - 3)
3708               plci->dtmf_parameter_length = (byte)(m->length - 3);
3709             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3710               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3711             for (i = 0; i < plci->dtmf_parameter_length; i++)
3712               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3713             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3714               dtmf_parameter_write (plci);
3715             break;
3716
3717           }
3718         }
3719         v_plci = plci;
3720       }
3721
3722       if(!v_plci)
3723       {
3724         Info = _WRONG_IDENTIFIER;
3725         break;
3726       }
3727       if(m->length){
3728         add_ss(v_plci,FTY,m);
3729         sig_req(v_plci,TEL_CTRL,0);
3730         send_req(v_plci);
3731       }
3732       else Info = _WRONG_MESSAGE_FORMAT;
3733
3734       break;
3735
3736     case _DI_OPTIONS_REQUEST:
3737       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3738         Info = _WRONG_MESSAGE_FORMAT;
3739         break;
3740       }
3741       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3742       {
3743         Info = _FACILITY_NOT_SUPPORTED;
3744         break;
3745       }
3746       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3747       break;
3748
3749
3750
3751     default:
3752       Info = _WRONG_MESSAGE_FORMAT;
3753       break;
3754     }
3755   }
3756
3757   sendf(appl,
3758         _MANUFACTURER_R|CONFIRM,
3759         Id,
3760         Number,
3761         "dww",_DI_MANU_ID,command,Info);
3762   return false;
3763 }
3764
3765
3766 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3767                              PLCI *plci, APPL *appl, API_PARSE *msg)
3768 {
3769   word indication;
3770
3771     API_PARSE m_parms[3];
3772   API_PARSE *ncpi;
3773     API_PARSE fax_parms[9];
3774   word i;
3775   byte len;
3776
3777
3778   dbug(1,dprintf("manufacturer_res"));
3779
3780   if ((msg[0].length == 0)
3781    || (msg[1].length == 0)
3782    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3783   {
3784     return false;
3785   }
3786   indication = GET_WORD(msg[1].info);
3787   switch (indication)
3788   {
3789
3790   case _DI_NEGOTIATE_B3:
3791     if(!plci)
3792       break;
3793     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3794      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3795     {
3796       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3797       break;
3798     }
3799     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3800     {
3801       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3802       break;
3803     }
3804     ncpi = &m_parms[1];
3805     len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3806     if (plci->fax_connect_info_length < len)
3807     {
3808       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3809       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3810     }
3811     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3812     {
3813       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3814     }
3815     else
3816     {
3817       if (plci->fax_connect_info_length <= len)
3818         plci->fax_connect_info_buffer[len] = 0;
3819       len += 1 + plci->fax_connect_info_buffer[len];
3820       if (plci->fax_connect_info_length <= len)
3821         plci->fax_connect_info_buffer[len] = 0;
3822       len += 1 + plci->fax_connect_info_buffer[len];
3823       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3824         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3825       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3826       for (i = 0; i < fax_parms[7].length; i++)
3827         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3828     }
3829     plci->fax_connect_info_length = len;
3830     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3831     start_internal_command (Id, plci, fax_edata_ack_command);
3832     break;
3833
3834   }
3835   return false;
3836 }
3837
3838 /*------------------------------------------------------------------*/
3839 /* IDI callback function                                            */
3840 /*------------------------------------------------------------------*/
3841
3842 void   callback(ENTITY   * e)
3843 {
3844   DIVA_CAPI_ADAPTER   * a;
3845   APPL   * appl;
3846   PLCI   * plci;
3847   CAPI_MSG   *m;
3848   word i, j;
3849   byte rc;
3850   byte ch;
3851   byte req;
3852   byte global_req;
3853   int no_cancel_rc;
3854
3855   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3856                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3857
3858   a = &(adapter[(byte)e->user[0]]);
3859   plci = &(a->plci[e->user[1]]);
3860   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3861
3862   /*
3863      If new protocol code and new XDI is used then CAPI should work
3864      fully in accordance with IDI cpec an look on callback field instead
3865      of Rc field for return codes.
3866    */
3867   if (((e->complete == 0xff) && no_cancel_rc) ||
3868       (e->Rc && !no_cancel_rc)) {
3869     rc = e->Rc;
3870     ch = e->RcCh;
3871     req = e->Req;
3872     e->Rc = 0;
3873
3874     if (e->user[0] & 0x8000)
3875     {
3876       /*
3877          If REMOVE request was sent then we have to wait until
3878          return code with Id set to zero arrives.
3879          All other return codes should be ignored.
3880          */
3881       if (req == REMOVE)
3882       {
3883         if (e->Id)
3884         {
3885           dbug(1,dprintf("cancel RC in REMOVE state"));
3886           return;
3887         }
3888         channel_flow_control_remove (plci);
3889         for (i = 0; i < 256; i++)
3890         {
3891           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3892             a->FlowControlIdTable[i] = 0;
3893         }
3894         plci->nl_remove_id = 0;
3895         if (plci->rx_dma_descriptor > 0) {
3896           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3897           plci->rx_dma_descriptor = 0;
3898         }
3899       }
3900       if (rc == OK_FC)
3901       {
3902         a->FlowControlIdTable[ch] = e->Id;
3903         a->FlowControlSkipTable[ch] = 0;
3904
3905         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3906         a->ch_flow_plci[ch] = plci->Id;
3907         plci->nl_req = 0;
3908       }
3909       else
3910       {
3911         /*
3912           Cancel return codes self, if feature was requested
3913           */
3914         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3915           a->FlowControlIdTable[ch] = 0;
3916           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3917             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3918             return;
3919           }
3920         }
3921
3922         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3923         {
3924           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3925           if (ch == e->ReqCh)
3926             plci->nl_req = 0;
3927         }
3928         else
3929           plci->nl_req = 0;
3930       }
3931       if (plci->nl_req)
3932         control_rc (plci, 0, rc, ch, 0, true);
3933       else
3934       {
3935         if (req == N_XON)
3936         {
3937           channel_x_on (plci, ch);
3938           if (plci->internal_command)
3939             control_rc (plci, req, rc, ch, 0, true);
3940         }
3941         else
3942         {
3943           if (plci->nl_global_req)
3944           {
3945             global_req = plci->nl_global_req;
3946             plci->nl_global_req = 0;
3947             if (rc != ASSIGN_OK) {
3948               e->Id = 0;
3949               if (plci->rx_dma_descriptor > 0) {
3950                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3951                 plci->rx_dma_descriptor = 0;
3952               }
3953             }
3954             channel_xmit_xon (plci);
3955             control_rc (plci, 0, rc, ch, global_req, true);
3956           }
3957           else if (plci->data_sent)
3958           {
3959             channel_xmit_xon (plci);
3960             plci->data_sent = false;
3961             plci->NL.XNum = 1;
3962             data_rc (plci, ch);
3963             if (plci->internal_command)
3964               control_rc (plci, req, rc, ch, 0, true);
3965           }
3966           else
3967           {
3968             channel_xmit_xon (plci);
3969             control_rc (plci, req, rc, ch, 0, true);
3970           }
3971         }
3972       }
3973     }
3974     else
3975     {
3976       /*
3977          If REMOVE request was sent then we have to wait until
3978          return code with Id set to zero arrives.
3979          All other return codes should be ignored.
3980          */
3981       if (req == REMOVE)
3982       {
3983         if (e->Id)
3984         {
3985           dbug(1,dprintf("cancel RC in REMOVE state"));
3986           return;
3987         }
3988         plci->sig_remove_id = 0;
3989       }
3990       plci->sig_req = 0;
3991       if (plci->sig_global_req)
3992       {
3993         global_req = plci->sig_global_req;
3994         plci->sig_global_req = 0;
3995         if (rc != ASSIGN_OK)
3996           e->Id = 0;
3997         channel_xmit_xon (plci);
3998         control_rc (plci, 0, rc, ch, global_req, false);
3999       }
4000       else
4001       {
4002         channel_xmit_xon (plci);
4003         control_rc (plci, req, rc, ch, 0, false);
4004       }
4005     }
4006     /*
4007       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4008       same callback. Also if new XDI and protocol code used then jump
4009       direct to finish.
4010       */
4011     if (no_cancel_rc) {
4012       channel_xmit_xon(plci);
4013       goto capi_callback_suffix;
4014     }
4015   }
4016
4017   channel_xmit_xon(plci);
4018
4019   if (e->Ind) {
4020     if (e->user[0] &0x8000) {
4021       byte Ind = e->Ind & 0x0f;
4022       byte Ch = e->IndCh;
4023       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4024           (a->ch_flow_plci[Ch] == plci->Id)) {
4025         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4026           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4027         }
4028         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4029       }
4030       nl_ind(plci);
4031       if ((e->RNR != 1) &&
4032           (a->ch_flow_plci[Ch] == plci->Id) &&
4033           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4034         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4035         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4036       }
4037     } else {
4038       sig_ind(plci);
4039     }
4040     e->Ind = 0;
4041   }
4042
4043 capi_callback_suffix:
4044
4045   while (!plci->req_in
4046    && !plci->internal_command
4047    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4048   {
4049     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4050
4051     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4052
4053     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4054     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4055     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4056       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4057     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4058     {
4059       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4060       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4061     }
4062     else
4063     {
4064       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4065     }
4066     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4067     {
4068       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4069       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4070     }
4071     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4072     {
4073       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4074       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4075     }
4076     i = api_put (appl, m);
4077     if (i != 0)
4078     {
4079       if (m->header.command == _DATA_B3_R)
4080
4081         TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4082
4083       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4084       break;
4085     }
4086
4087     if (plci->li_notify_update)
4088     {
4089       plci->li_notify_update = false;
4090       mixer_notify_update (plci, false);
4091     }
4092
4093   }
4094   send_data(plci);
4095   send_req(plci);
4096 }
4097
4098
4099 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4100                        byte nl_rc)
4101 {
4102   dword Id;
4103   dword rId;
4104   word Number;
4105   word Info=0;
4106   word i;
4107   word ncci;
4108   DIVA_CAPI_ADAPTER   * a;
4109   APPL   * appl;
4110   PLCI   * rplci;
4111     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4112     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4113
4114   if (!plci) {
4115     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4116     return;
4117   }
4118   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4119   if(plci->req_in!=plci->req_out)
4120   {
4121     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4122     {
4123       dbug(1,dprintf("req_1return"));
4124       return;
4125     }
4126     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4127   }
4128   plci->req_in = plci->req_in_start = plci->req_out = 0;
4129   dbug(1,dprintf("control_rc"));
4130
4131   appl = plci->appl;
4132   a = plci->adapter;
4133   ncci = a->ch_ncci[ch];
4134   if(appl)
4135   {
4136     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4137     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4138     Number = plci->number;
4139     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));
4140     dbug(1,dprintf("channels=0x%x",plci->channels));
4141     if (plci_remove_check(plci))
4142       return;
4143     if(req==REMOVE && rc==ASSIGN_OK)
4144     {
4145       sig_req(plci,HANGUP,0);
4146       sig_req(plci,REMOVE,0);
4147       send_req(plci);
4148     }
4149     if(plci->command)
4150     {
4151       switch(plci->command)
4152       {
4153       case C_HOLD_REQ:
4154         dbug(1,dprintf("HoldRC=0x%x",rc));
4155         SSparms[1] = (byte)S_HOLD;
4156         if(rc!=OK)
4157         {
4158           plci->SuppState = IDLE;
4159           Info = 0x2001;
4160         }
4161         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4162         break;
4163
4164       case C_RETRIEVE_REQ:
4165         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4166         SSparms[1] = (byte)S_RETRIEVE;
4167         if(rc!=OK)
4168         {
4169           plci->SuppState = CALL_HELD;
4170           Info = 0x2001;
4171         }
4172         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4173         break;
4174
4175       case _INFO_R:
4176         dbug(1,dprintf("InfoRC=0x%x",rc));
4177         if(rc!=OK) Info=_WRONG_STATE;
4178         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4179         break;
4180
4181       case _CONNECT_R:
4182         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4183         if (plci->State == INC_DIS_PENDING)
4184           break;
4185         if(plci->Sig.Id!=0xff)
4186         {
4187           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4188            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4189           {
4190             dbug(1,dprintf("No more IDs/Call_Req failed"));
4191             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4192             plci_remove(plci);
4193             plci->State = IDLE;
4194             break;
4195           }
4196           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4197           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4198         }
4199         else /* D-ch activation */
4200         {
4201           if (rc != ASSIGN_OK)
4202           {
4203             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4204             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4205             plci_remove(plci);
4206             plci->State = IDLE;
4207             break;
4208           }
4209           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4210           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4211           plci->State = INC_ACT_PENDING;
4212         }
4213         break;
4214
4215       case _CONNECT_I|RESPONSE:
4216         if (plci->State != INC_DIS_PENDING)
4217           plci->State = INC_CON_ACCEPT;
4218         break;
4219
4220       case _DISCONNECT_R:
4221         if (plci->State == INC_DIS_PENDING)
4222           break;
4223         if(plci->Sig.Id!=0xff)
4224         {
4225           plci->State = OUTG_DIS_PENDING;
4226           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4227         }
4228         break;
4229
4230       case SUSPEND_REQ:
4231         break;
4232
4233       case RESUME_REQ:
4234         break;
4235
4236       case _CONNECT_B3_R:
4237         if(rc!=OK)
4238         {
4239           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4240           break;
4241         }
4242         ncci = get_ncci (plci, ch, 0);
4243         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4244         plci->channels++;
4245         if(req==N_RESET)
4246         {
4247           a->ncci_state[ncci] = INC_ACT_PENDING;
4248           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4249           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4250         }
4251         else
4252         {
4253           a->ncci_state[ncci] = OUTG_CON_PENDING;
4254           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4255         }
4256         break;
4257
4258       case _CONNECT_B3_I|RESPONSE:
4259         break;
4260
4261       case _RESET_B3_R:
4262 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4263         break;
4264
4265       case _DISCONNECT_B3_R:
4266         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4267         break;
4268
4269       case _MANUFACTURER_R:
4270         break;
4271
4272       case PERM_LIST_REQ:
4273         if(rc!=OK)
4274         {
4275           Info = _WRONG_IDENTIFIER;
4276           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4277           plci_remove(plci);
4278         }
4279         else
4280           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4281         break;
4282
4283       default:
4284         break;
4285       }
4286       plci->command = 0;
4287     }
4288     else if (plci->internal_command)
4289     {
4290       switch(plci->internal_command)
4291       {
4292       case BLOCK_PLCI:
4293         return;
4294
4295       case GET_MWI_STATE:
4296         if(rc==OK) /* command supported, wait for indication */
4297         {
4298           return;
4299         }
4300         plci_remove(plci);
4301         break;
4302
4303         /* Get Supported Services */
4304       case GETSERV_REQ_PEND:
4305         if(rc==OK) /* command supported, wait for indication */
4306         {
4307           break;
4308         }
4309         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4310         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4311         plci_remove(plci);
4312         break;
4313
4314       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4315       case INTERR_NUMBERS_REQ_PEND:
4316       case CF_START_PEND:                  /* Call Forwarding Start pending */
4317       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4318       case CCBS_REQUEST_REQ_PEND:
4319       case CCBS_DEACTIVATE_REQ_PEND:
4320       case CCBS_INTERROGATE_REQ_PEND:
4321         switch(plci->internal_command)
4322         {
4323           case INTERR_DIVERSION_REQ_PEND:
4324             SSparms[1] = S_INTERROGATE_DIVERSION;
4325             break;
4326           case INTERR_NUMBERS_REQ_PEND:
4327             SSparms[1] = S_INTERROGATE_NUMBERS;
4328             break;
4329           case CF_START_PEND:
4330             SSparms[1] = S_CALL_FORWARDING_START;
4331             break;
4332           case CF_STOP_PEND:
4333             SSparms[1] = S_CALL_FORWARDING_STOP;
4334             break;
4335           case CCBS_REQUEST_REQ_PEND:
4336             SSparms[1] = S_CCBS_REQUEST;
4337             break;
4338           case CCBS_DEACTIVATE_REQ_PEND:
4339             SSparms[1] = S_CCBS_DEACTIVATE;
4340             break;
4341           case CCBS_INTERROGATE_REQ_PEND:
4342             SSparms[1] = S_CCBS_INTERROGATE;
4343             break;
4344         }
4345         if(global_req==ASSIGN)
4346         {
4347           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4348           return;
4349         }
4350         if(!plci->appl) break;
4351         if(rc==ISDN_GUARD_REJ)
4352         {
4353           Info = _CAPI_GUARD_ERROR;
4354         }
4355         else if(rc!=OK)
4356         {
4357           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4358         }
4359         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4360               plci->number,"wws",Info,(word)3,SSparms);
4361         if(Info) plci_remove(plci);
4362         break;
4363
4364         /* 3pty conference pending */
4365       case PTY_REQ_PEND:
4366         if(!plci->relatedPTYPLCI) break;
4367         rplci = plci->relatedPTYPLCI;
4368         SSparms[1] = plci->ptyState;
4369         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4370         if(rplci->tel) rId|=EXT_CONTROLLER;
4371         if(rc!=OK)
4372         {
4373           Info = 0x300E; /* not supported */
4374           plci->relatedPTYPLCI = NULL;
4375           plci->ptyState = 0;
4376         }
4377         sendf(rplci->appl,
4378               _FACILITY_R|CONFIRM,
4379               rId,
4380               plci->number,
4381               "wws",Info,(word)3,SSparms);
4382         break;
4383
4384         /* Explicit Call Transfer pending */
4385       case ECT_REQ_PEND:
4386         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4387         if(!plci->relatedPTYPLCI) break;
4388         rplci = plci->relatedPTYPLCI;
4389         SSparms[1] = S_ECT;
4390         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4391         if(rplci->tel) rId|=EXT_CONTROLLER;
4392         if(rc!=OK)
4393         {
4394           Info = 0x300E; /* not supported */
4395           plci->relatedPTYPLCI = NULL;
4396           plci->ptyState = 0;
4397         }
4398         sendf(rplci->appl,
4399               _FACILITY_R|CONFIRM,
4400               rId,
4401               plci->number,
4402               "wws",Info,(word)3,SSparms);
4403         break;
4404
4405       case _MANUFACTURER_R:
4406         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4407         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4408         {
4409           dbug(1,dprintf("No more IDs"));
4410           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4411           plci_remove(plci);  /* after codec init, internal codec commands pending */
4412         }
4413         break;
4414
4415       case _CONNECT_R:
4416         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4417         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4418         {
4419           dbug(1,dprintf("No more IDs"));
4420           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4421           plci_remove(plci);  /* after codec init, internal codec commands pending */
4422         }
4423         break;
4424
4425       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4426         return;
4427
4428       case PERM_COD_CALL:
4429         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4430         plci->internal_command = PERM_COD_CONN_PEND;
4431         return;
4432
4433       case PERM_COD_ASSIGN:
4434         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4435         if(rc!=ASSIGN_OK) break;
4436         sig_req(plci,CALL_REQ,0);
4437         send_req(plci);
4438         plci->internal_command = PERM_COD_CALL;
4439         return;
4440
4441         /* Null Call Reference Request pending */
4442       case C_NCR_FAC_REQ:
4443         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4444         if(global_req==ASSIGN)
4445         {
4446           if(rc==ASSIGN_OK)
4447           {
4448             return;
4449           }
4450           else
4451           {
4452             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4453             appl->NullCREnable = false;
4454             plci_remove(plci);
4455           }
4456         }
4457         else if(req==NCR_FACILITY)
4458         {
4459           if(rc==OK)
4460           {
4461             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4462           }
4463           else
4464           {
4465             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4466             appl->NullCREnable = false;
4467           }
4468           plci_remove(plci);
4469         }
4470         break;
4471
4472       case HOOK_ON_REQ:
4473         if(plci->channels)
4474         {
4475           if(a->ncci_state[ncci]==CONNECTED)
4476           {
4477             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4478             cleanup_ncci_data (plci, ncci);
4479             nl_req_ncci(plci,N_DISC,(byte)ncci);
4480           }
4481           break;
4482         }
4483         break;
4484
4485       case HOOK_OFF_REQ:
4486         if (plci->State == INC_DIS_PENDING)
4487           break;
4488         sig_req(plci,CALL_REQ,0);
4489         send_req(plci);
4490         plci->State=OUTG_CON_PENDING;
4491         break;
4492
4493
4494       case MWI_ACTIVATE_REQ_PEND:
4495       case MWI_DEACTIVATE_REQ_PEND:
4496         if(global_req == ASSIGN && rc==ASSIGN_OK)
4497         {
4498           dbug(1,dprintf("MWI_REQ assigned"));
4499           return;
4500         }
4501         else if(rc!=OK)
4502         {                 
4503           if(rc==WRONG_IE)
4504           {
4505             Info = 0x2007; /* Illegal message parameter coding */
4506             dbug(1,dprintf("MWI_REQ invalid parameter"));
4507           }
4508           else
4509           {
4510             Info = 0x300B; /* not supported */                      
4511             dbug(1,dprintf("MWI_REQ not supported"));
4512           }
4513           /* 0x3010: Request not allowed in this state */
4514           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4515                     
4516         }
4517         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4518         {
4519           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4520         }
4521         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4522
4523         if(plci->cr_enquiry)
4524         {
4525           sendf(plci->appl,
4526                 _FACILITY_R|CONFIRM,
4527                 Id&0xf,
4528                 plci->number,
4529                 "wws",Info,(word)3,SSparms);
4530           if(rc!=OK) plci_remove(plci);
4531         }
4532         else
4533         {
4534           sendf(plci->appl,
4535                 _FACILITY_R|CONFIRM,
4536                 Id,
4537                 plci->number,
4538                 "wws",Info,(word)3,SSparms);
4539         }
4540         break;
4541
4542       case CONF_BEGIN_REQ_PEND:
4543       case CONF_ADD_REQ_PEND:
4544       case CONF_SPLIT_REQ_PEND:
4545       case CONF_DROP_REQ_PEND:
4546       case CONF_ISOLATE_REQ_PEND:
4547       case CONF_REATTACH_REQ_PEND:
4548         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4549         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4550         rplci = plci;
4551         rId = Id;
4552         switch(plci->internal_command)
4553         {
4554           case CONF_BEGIN_REQ_PEND:
4555             SSparms[1] = S_CONF_BEGIN;
4556             break;
4557           case CONF_ADD_REQ_PEND:
4558             SSparms[1] = S_CONF_ADD;
4559             rplci = plci->relatedPTYPLCI;
4560             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4561             break;
4562           case CONF_SPLIT_REQ_PEND:
4563             SSparms[1] = S_CONF_SPLIT;
4564             break;
4565           case CONF_DROP_REQ_PEND:
4566             SSparms[1] = S_CONF_DROP;
4567             break;
4568           case CONF_ISOLATE_REQ_PEND:
4569             SSparms[1] = S_CONF_ISOLATE;
4570             break;
4571           case CONF_REATTACH_REQ_PEND:
4572             SSparms[1] = S_CONF_REATTACH;
4573             break;
4574         }
4575         
4576         if(rc!=OK)
4577         {
4578           Info = 0x300E; /* not supported */
4579           plci->relatedPTYPLCI = NULL;
4580           plci->ptyState = 0;
4581         }
4582         sendf(rplci->appl,
4583               _FACILITY_R|CONFIRM,
4584               rId,
4585               plci->number,
4586               "wws",Info,(word)3,SSparms);
4587         break;
4588
4589       case VSWITCH_REQ_PEND:
4590         if(rc!=OK)
4591         {
4592           if(plci->relatedPTYPLCI)
4593           {
4594             plci->relatedPTYPLCI->vswitchstate=0;
4595             plci->relatedPTYPLCI->vsprot=0;
4596             plci->relatedPTYPLCI->vsprotdialect=0;    
4597           }
4598           plci->vswitchstate=0;
4599           plci->vsprot=0;
4600           plci->vsprotdialect=0;
4601         }
4602         else
4603         {
4604           if(plci->relatedPTYPLCI &&
4605              plci->vswitchstate==1 &&
4606              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4607             plci->vswitchstate=3;
4608         }
4609         break;
4610
4611   /* Call Deflection Request pending (SSCT) */
4612       case CD_REQ_PEND:
4613         SSparms[1] = S_CALL_DEFLECTION;
4614         if(rc!=OK)
4615         {
4616           Info = 0x300E; /* not supported */
4617           plci->appl->CDEnable = 0;
4618         }  
4619         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4620           plci->number,"wws",Info,(word)3,SSparms);
4621         break;
4622
4623       case RTP_CONNECT_B3_REQ_COMMAND_2:
4624         if (rc == OK)
4625         {
4626           ncci = get_ncci (plci, ch, 0);
4627           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4628           plci->channels++;
4629           a->ncci_state[ncci] = OUTG_CON_PENDING;
4630         }
4631
4632       default:
4633         if (plci->internal_command_queue[0])
4634         {
4635           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4636           if (plci->internal_command)
4637             return;
4638         }
4639         break;
4640       }
4641       next_internal_command (Id, plci);
4642     }
4643   }
4644   else /* appl==0 */
4645   {
4646     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4647     if(plci->tel) Id|=EXT_CONTROLLER;
4648
4649     switch(plci->internal_command)
4650     {
4651     case BLOCK_PLCI:
4652       return;
4653
4654     case START_L1_SIG_ASSIGN_PEND:
4655     case REM_L1_SIG_ASSIGN_PEND:
4656       if(global_req == ASSIGN)
4657       {
4658         break;
4659       }
4660       else
4661       {
4662         dbug(1,dprintf("***L1 Req rem PLCI"));
4663         plci->internal_command = 0;
4664         sig_req(plci,REMOVE,0);
4665         send_req(plci);
4666       }
4667       break;
4668
4669       /* Call Deflection Request pending, just no appl ptr assigned */
4670     case CD_REQ_PEND:
4671       SSparms[1] = S_CALL_DEFLECTION;
4672       if(rc!=OK)
4673       {
4674         Info = 0x300E; /* not supported */
4675       }
4676       for(i=0; i<max_appl; i++)
4677       {
4678         if(application[i].CDEnable)
4679         {
4680           if(!application[i].Id) application[i].CDEnable = 0;
4681           else
4682           {
4683             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4684                   plci->number,"wws",Info,(word)3,SSparms);
4685             if(Info) application[i].CDEnable = 0;
4686           }
4687         }
4688       }
4689       plci->internal_command = 0;
4690       break;
4691
4692     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4693       return;
4694
4695     case PERM_COD_CALL:
4696       plci->internal_command = PERM_COD_CONN_PEND;
4697       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4698       return;
4699
4700     case PERM_COD_ASSIGN:
4701       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4702       plci->internal_command = 0;
4703       if(rc!=ASSIGN_OK) break;
4704       plci->internal_command = PERM_COD_CALL;
4705       sig_req(plci,CALL_REQ,0);
4706       send_req(plci);
4707       return;
4708
4709     case LISTEN_SIG_ASSIGN_PEND:
4710       if(rc == ASSIGN_OK)
4711       {
4712         plci->internal_command = 0;
4713         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4714         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4715         sig_req(plci,INDICATE_REQ,0);
4716         send_req(plci);
4717       }
4718       else
4719       {
4720         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4721         a->listen_active--;
4722         plci_remove(plci);
4723         plci->State = IDLE;
4724       }
4725       break;
4726
4727     case USELAW_REQ:
4728       if(global_req == ASSIGN)
4729       {
4730         if (rc==ASSIGN_OK)
4731       {
4732         sig_req(plci,LAW_REQ,0);
4733         send_req(plci);
4734         dbug(1,dprintf("Auto-Law assigned"));
4735         }
4736         else
4737         {
4738           dbug(1,dprintf("Auto-Law assign failed"));
4739           a->automatic_law = 3;
4740           plci->internal_command = 0;
4741           a->automatic_lawPLCI = NULL;
4742         }
4743         break;
4744       }
4745       else if(req == LAW_REQ && rc==OK)
4746       {
4747         dbug(1,dprintf("Auto-Law initiated"));
4748         a->automatic_law = 2;
4749         plci->internal_command = 0;
4750       }
4751       else
4752       {
4753         dbug(1,dprintf("Auto-Law not supported"));
4754         a->automatic_law = 3;
4755         plci->internal_command = 0;
4756         sig_req(plci,REMOVE,0);
4757         send_req(plci);
4758         a->automatic_lawPLCI = NULL;
4759       }
4760       break;
4761     }
4762     plci_remove_check(plci);
4763   }
4764 }
4765
4766 static void data_rc(PLCI *plci, byte ch)
4767 {
4768   dword Id;
4769   DIVA_CAPI_ADAPTER   * a;
4770   NCCI   *ncci_ptr;
4771   DATA_B3_DESC   *data;
4772   word ncci;
4773
4774   if (plci->appl)
4775   {
4776     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4777     a = plci->adapter;
4778     ncci = a->ch_ncci[ch];
4779     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4780     {
4781       ncci_ptr = &(a->ncci[ncci]);
4782       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4783       if (ncci_ptr->data_pending)
4784       {
4785         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4786         if (!(data->Flags &4) && a->ncci_state[ncci])
4787         {
4788           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4789           if(plci->tel) Id|=EXT_CONTROLLER;
4790           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4791                 "ww",data->Handle,0);
4792         }
4793         (ncci_ptr->data_out)++;
4794         if (ncci_ptr->data_out == MAX_DATA_B3)
4795           ncci_ptr->data_out = 0;
4796         (ncci_ptr->data_pending)--;
4797       }
4798     }
4799   }
4800 }
4801
4802 static void data_ack(PLCI *plci, byte ch)
4803 {
4804   dword Id;
4805   DIVA_CAPI_ADAPTER   * a;
4806   NCCI   *ncci_ptr;
4807   word ncci;
4808
4809   a = plci->adapter;
4810   ncci = a->ch_ncci[ch];
4811   ncci_ptr = &(a->ncci[ncci]);
4812   if (ncci_ptr->data_ack_pending)
4813   {
4814     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4815     {
4816       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4817       if(plci->tel) Id|=EXT_CONTROLLER;
4818       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4819             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4820     }
4821     (ncci_ptr->data_ack_out)++;
4822     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4823       ncci_ptr->data_ack_out = 0;
4824     (ncci_ptr->data_ack_pending)--;
4825   }
4826 }
4827
4828 static void sig_ind(PLCI *plci)
4829 {
4830   dword x_Id;
4831   dword Id;
4832   dword rId;
4833   word Number = 0;
4834   word i;
4835   word cip;
4836   dword cip_mask;
4837   byte   *ie;
4838   DIVA_CAPI_ADAPTER   * a;
4839     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4840 #define MAXPARMSIDS 31
4841     byte   * parms[MAXPARMSIDS];
4842     byte   * add_i[4];
4843     byte   * multi_fac_parms[MAX_MULTI_IE];
4844     byte   * multi_pi_parms [MAX_MULTI_IE];
4845     byte   * multi_ssext_parms [MAX_MULTI_IE];
4846     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4847
4848     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4849
4850   byte ai_len;
4851     byte   *esc_chi = "";
4852     byte   *esc_law = "";
4853     byte   *pty_cai = "";
4854     byte   *esc_cr  = "";
4855     byte   *esc_profile = "";
4856
4857     byte facility[256];
4858   PLCI   * tplci = NULL;
4859   byte chi[] = "\x02\x18\x01";
4860   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4861     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4862   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4863   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4864   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4865   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4866     word parms_id[] =
4867          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4868           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4869           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4870           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4871           /* 14 FTY repl by ESC_CHI */
4872           /* 18 PI  repl by ESC_LAW */
4873          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4874      word multi_fac_id[] = {1, FTY};
4875      word multi_pi_id[]  = {1, PI};
4876      word multi_CiPN_id[]  = {1, OAD};
4877      word multi_ssext_id[]  = {1, ESC_SSEXT};
4878
4879      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4880
4881   byte   * cau;
4882   word ncci;
4883     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4884     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4885     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4886     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4887   byte force_mt_info = false;
4888   byte dir;
4889   dword d;
4890   word w;
4891
4892   a = plci->adapter;
4893   Id = ((word)plci->Id<<8)|a->Id;
4894   PUT_WORD(&SS_Ind[4],0x0000);
4895
4896   if (plci->sig_remove_id)
4897   {
4898     plci->Sig.RNR = 2; /* discard */
4899     dbug(1,dprintf("SIG discard while remove pending"));
4900     return;
4901   }
4902   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4903   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4904     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4905   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4906   {
4907     plci->Sig.RNR = 1;
4908     return;
4909   }
4910   if(plci->Sig.Ind==HANGUP && plci->channels)
4911   {
4912     plci->Sig.RNR = 1;
4913     plci->hangup_flow_ctrl_timer++;
4914     /* recover the network layer after timeout */
4915     if(plci->hangup_flow_ctrl_timer==100)
4916     {
4917       dbug(1,dprintf("Exceptional disc"));
4918       plci->Sig.RNR = 0;
4919       plci->hangup_flow_ctrl_timer = 0;
4920       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4921       {
4922         if (a->ncci_plci[ncci] == plci->Id)
4923         {
4924           cleanup_ncci_data (plci, ncci);
4925           if(plci->channels)plci->channels--;
4926           if (plci->appl)
4927             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4928         }
4929       }
4930       if (plci->appl)
4931         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4932       plci_remove(plci);
4933       plci->State=IDLE;
4934     }
4935     return;
4936   }
4937
4938   /* do first parse the info with no OAD in, because OAD will be converted */
4939   /* first the multiple facility IE, then mult. progress ind.              */
4940   /* then the parameters for the info_ind + conn_ind                       */
4941   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4942   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4943   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4944
4945   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4946
4947   IndParse(plci,parms_id,parms,0);
4948   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4949   esc_chi  = parms[14];
4950   esc_law  = parms[18];
4951   pty_cai  = parms[24];
4952   esc_cr   = parms[25];
4953   esc_profile = parms[27];
4954   if(esc_cr[0] && plci)
4955   {
4956     if(plci->cr_enquiry && plci->appl)
4957     {
4958       plci->cr_enquiry = false;
4959       /* d = MANU_ID            */
4960       /* w = m_command          */
4961       /* b = total length       */
4962       /* b = indication type    */
4963       /* b = length of all IEs  */
4964       /* b = IE1                */
4965       /* S = IE1 length + cont. */
4966       /* b = IE2                */
4967       /* S = IE2 length + cont. */
4968       sendf(plci->appl,
4969         _MANUFACTURER_I,
4970         Id,
4971         0,
4972         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4973         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);
4974     }
4975   }
4976   /* create the additional info structure                                  */
4977   add_i[1] = parms[15]; /* KEY of additional info */
4978   add_i[2] = parms[11]; /* UUI of additional info */
4979   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4980
4981   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4982   /* indication returns by the card if requested by the function           */
4983   /* AutomaticLaw() after driver init                                      */
4984   if (a->automatic_law<4)
4985   {
4986     if(esc_law[0]){
4987       if(esc_law[2]){
4988         dbug(0,dprintf("u-Law selected"));
4989         a->u_law = 1;
4990       }
4991       else {
4992         dbug(0,dprintf("a-Law selected"));
4993         a->u_law = 0;
4994       }
4995       a->automatic_law = 4;
4996       if(plci==a->automatic_lawPLCI) {
4997         plci->internal_command = 0;
4998         sig_req(plci,REMOVE,0);
4999         send_req(plci);
5000         a->automatic_lawPLCI = NULL;
5001       }
5002     }
5003     if (esc_profile[0])
5004     {
5005       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5006         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
5007         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
5008         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
5009
5010       a->profile.Global_Options &= 0x000000ffL;
5011       a->profile.B1_Protocols &= 0x000003ffL;
5012       a->profile.B2_Protocols &= 0x00001fdfL;
5013       a->profile.B3_Protocols &= 0x000000b7L;
5014
5015       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
5016         GL_BCHANNEL_OPERATION_SUPPORTED;
5017       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
5018       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
5019       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5020       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5021       a->man_profile.private_options = 0;
5022
5023       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5024       {
5025         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5026         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5027       }
5028
5029
5030       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5031         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5032       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5033       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5034
5035
5036       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5037         a->man_profile.private_options |= 1L << PRIVATE_T38;
5038
5039
5040       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5041         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5042
5043
5044       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5045         a->man_profile.private_options |= 1L << PRIVATE_V18;
5046
5047
5048       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5049         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5050
5051
5052       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5053         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5054
5055
5056       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5057         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5058
5059
5060       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5061         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5062
5063
5064       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5065         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5066
5067     }
5068     else
5069     {
5070       a->profile.Global_Options &= 0x0000007fL;
5071       a->profile.B1_Protocols &= 0x000003dfL;
5072       a->profile.B2_Protocols &= 0x00001adfL;
5073       a->profile.B3_Protocols &= 0x000000b7L;
5074       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5075     }
5076     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5077       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5078     {
5079       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5080     }
5081     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5082     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5083       UnMapController (a->Id), a->profile.Global_Options,
5084       a->profile.B1_Protocols, a->profile.B2_Protocols,
5085       a->profile.B3_Protocols, a->manufacturer_features));
5086   }
5087   /* codec plci for the handset/hook state support is just an internal id  */
5088   if(plci!=a->AdvCodecPLCI)
5089   {
5090     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5091     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5092     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5093     SendInfo(plci,Id, parms, force_mt_info);
5094
5095     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5096
5097   }
5098
5099   /* switch the codec to the b-channel                                     */
5100   if(esc_chi[0] && plci && !plci->SuppState){
5101     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5102     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5103     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5104     if(plci->tel==ADV_VOICE && plci->appl) {
5105       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5106     }
5107   }
5108
5109   if(plci->appl) Number = plci->appl->Number++;
5110
5111   switch(plci->Sig.Ind) {
5112   /* Response to Get_Supported_Services request */
5113   case S_SUPPORTED:
5114     dbug(1,dprintf("S_Supported"));
5115     if(!plci->appl) break;
5116     if(pty_cai[0]==4)
5117     {
5118       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5119     }
5120     else
5121     {
5122       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5123     }
5124     PUT_WORD (&CF_Ind[1], 0);
5125     PUT_WORD (&CF_Ind[4], 0);
5126     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5127     plci_remove(plci);
5128     break;
5129                     
5130   /* Supplementary Service rejected */
5131   case S_SERVICE_REJ:
5132     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5133     if(!pty_cai[0]) break;
5134     switch (pty_cai[5])
5135     {
5136     case ECT_EXECUTE:
5137     case THREE_PTY_END:
5138     case THREE_PTY_BEGIN:
5139       if(!plci->relatedPTYPLCI) break;
5140       tplci = plci->relatedPTYPLCI;
5141       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5142       if(tplci->tel) rId|=EXT_CONTROLLER;
5143       if(pty_cai[5]==ECT_EXECUTE)
5144       {
5145         PUT_WORD(&SS_Ind[1],S_ECT);
5146
5147         plci->vswitchstate=0;
5148         plci->relatedPTYPLCI->vswitchstate=0;
5149
5150       }
5151       else
5152       {
5153         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5154       }
5155       if(pty_cai[2]!=0xff)
5156       {
5157         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5158       }
5159       else
5160       {
5161         PUT_WORD(&SS_Ind[4],0x300E);
5162       }
5163       plci->relatedPTYPLCI = NULL;
5164       plci->ptyState = 0;
5165       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5166       break;
5167
5168     case CALL_DEFLECTION:
5169       if(pty_cai[2]!=0xff)
5170       {
5171         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5172       }
5173       else
5174       {
5175         PUT_WORD(&SS_Ind[4],0x300E);
5176       }
5177       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5178       for(i=0; i<max_appl; i++)
5179       {
5180         if(application[i].CDEnable)
5181         {
5182           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5183           application[i].CDEnable = false;
5184         }
5185       }
5186       break;
5187
5188     case DEACTIVATION_DIVERSION:
5189     case ACTIVATION_DIVERSION:
5190     case DIVERSION_INTERROGATE_CFU:
5191     case DIVERSION_INTERROGATE_CFB:
5192     case DIVERSION_INTERROGATE_CFNR:
5193     case DIVERSION_INTERROGATE_NUM:
5194     case CCBS_REQUEST:
5195     case CCBS_DEACTIVATE:
5196     case CCBS_INTERROGATE:
5197       if(!plci->appl) break;
5198       if(pty_cai[2]!=0xff)
5199       {
5200         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5201       }
5202       else
5203       {
5204         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5205       }
5206       switch (pty_cai[5])
5207       {
5208         case DEACTIVATION_DIVERSION:
5209           dbug(1,dprintf("Deact_Div"));
5210           Interr_Err_Ind[0]=0x9;
5211           Interr_Err_Ind[3]=0x6;
5212           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5213           break;
5214         case ACTIVATION_DIVERSION:
5215           dbug(1,dprintf("Act_Div"));
5216           Interr_Err_Ind[0]=0x9;
5217           Interr_Err_Ind[3]=0x6;
5218           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5219           break;
5220         case DIVERSION_INTERROGATE_CFU:
5221         case DIVERSION_INTERROGATE_CFB:
5222         case DIVERSION_INTERROGATE_CFNR:
5223           dbug(1,dprintf("Interr_Div"));
5224           Interr_Err_Ind[0]=0xa;
5225           Interr_Err_Ind[3]=0x7;
5226           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5227           break;
5228         case DIVERSION_INTERROGATE_NUM:
5229           dbug(1,dprintf("Interr_Num"));
5230           Interr_Err_Ind[0]=0xa;
5231           Interr_Err_Ind[3]=0x7;
5232           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5233           break;
5234         case CCBS_REQUEST:
5235           dbug(1,dprintf("CCBS Request"));
5236           Interr_Err_Ind[0]=0xd;
5237           Interr_Err_Ind[3]=0xa;
5238           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5239           break;
5240         case CCBS_DEACTIVATE:
5241           dbug(1,dprintf("CCBS Deactivate"));
5242           Interr_Err_Ind[0]=0x9;
5243           Interr_Err_Ind[3]=0x6;
5244           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5245           break;
5246         case CCBS_INTERROGATE:
5247           dbug(1,dprintf("CCBS Interrogate"));
5248           Interr_Err_Ind[0]=0xb;
5249           Interr_Err_Ind[3]=0x8;
5250           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5251           break;
5252       }
5253       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5254       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5255       plci_remove(plci);
5256       break;
5257     case ACTIVATION_MWI:      
5258     case DEACTIVATION_MWI:
5259       if(pty_cai[5]==ACTIVATION_MWI)
5260       {
5261         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5262       }
5263       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5264       
5265       if(pty_cai[2]!=0xff)
5266       {
5267         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5268       }
5269       else
5270       {
5271         PUT_WORD(&SS_Ind[4],0x300E);
5272       }
5273
5274       if(plci->cr_enquiry)
5275       {
5276         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5277         plci_remove(plci);
5278       }
5279       else
5280       {
5281         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5282       }
5283       break;
5284     case CONF_ADD: /* ERROR */
5285     case CONF_BEGIN:
5286     case CONF_DROP:
5287     case CONF_ISOLATE:
5288     case CONF_REATTACH:
5289       CONF_Ind[0]=9;
5290       CONF_Ind[3]=6;   
5291       switch(pty_cai[5])
5292       {
5293       case CONF_BEGIN:
5294           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5295           plci->ptyState = 0;
5296           break;
5297       case CONF_DROP:
5298           CONF_Ind[0]=5;
5299           CONF_Ind[3]=2;
5300           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5301           plci->ptyState = CONNECTED;
5302           break;
5303       case CONF_ISOLATE:
5304           CONF_Ind[0]=5;
5305           CONF_Ind[3]=2;
5306           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5307           plci->ptyState = CONNECTED;
5308           break;
5309       case CONF_REATTACH:
5310           CONF_Ind[0]=5;
5311           CONF_Ind[3]=2;
5312           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5313           plci->ptyState = CONNECTED;
5314           break;
5315       case CONF_ADD:
5316           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5317           plci->relatedPTYPLCI = NULL;
5318           tplci=plci->relatedPTYPLCI;
5319           if(tplci) tplci->ptyState = CONNECTED;
5320           plci->ptyState = CONNECTED;
5321           break;
5322       }
5323           
5324       if(pty_cai[2]!=0xff)
5325       {
5326         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5327       }
5328       else
5329       {
5330         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5331                                             within the required time */
5332       }
5333
5334       PUT_DWORD(&CONF_Ind[6],0x0);
5335       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5336       break;
5337     }
5338     break;
5339
5340   /* Supplementary Service indicates success */
5341   case S_SERVICE:
5342     dbug(1,dprintf("Service_Ind"));
5343     PUT_WORD (&CF_Ind[4], 0);
5344     switch (pty_cai[5])
5345     {
5346     case THREE_PTY_END:
5347     case THREE_PTY_BEGIN:
5348     case ECT_EXECUTE:
5349       if(!plci->relatedPTYPLCI) break;
5350       tplci = plci->relatedPTYPLCI;
5351       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5352       if(tplci->tel) rId|=EXT_CONTROLLER;
5353       if(pty_cai[5]==ECT_EXECUTE)
5354       {
5355         PUT_WORD(&SS_Ind[1],S_ECT);
5356
5357         if(plci->vswitchstate!=3)
5358         {
5359
5360         plci->ptyState = IDLE;
5361         plci->relatedPTYPLCI = NULL;
5362         plci->ptyState = 0;
5363
5364         }
5365
5366         dbug(1,dprintf("ECT OK"));
5367         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5368
5369
5370
5371       }
5372       else
5373       {
5374         switch (plci->ptyState)
5375         {
5376         case S_3PTY_BEGIN:
5377           plci->ptyState = CONNECTED;
5378           dbug(1,dprintf("3PTY ON"));
5379           break;
5380
5381         case S_3PTY_END:
5382           plci->ptyState = IDLE;
5383           plci->relatedPTYPLCI = NULL;
5384           plci->ptyState = 0;
5385           dbug(1,dprintf("3PTY OFF"));
5386           break;
5387         }
5388         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5389         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5390       }
5391       break;
5392
5393     case CALL_DEFLECTION:
5394       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5395       for(i=0; i<max_appl; i++)
5396       {
5397         if(application[i].CDEnable)
5398         {
5399           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5400           application[i].CDEnable = false;
5401         }
5402       }
5403       break;
5404
5405     case DEACTIVATION_DIVERSION:
5406     case ACTIVATION_DIVERSION:
5407       if(!plci->appl) break;
5408       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5409       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5410       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5411       plci_remove(plci);
5412       break;
5413
5414     case DIVERSION_INTERROGATE_CFU:
5415     case DIVERSION_INTERROGATE_CFB:
5416     case DIVERSION_INTERROGATE_CFNR:
5417     case DIVERSION_INTERROGATE_NUM:
5418     case CCBS_REQUEST:
5419     case CCBS_DEACTIVATE:
5420     case CCBS_INTERROGATE:
5421       if(!plci->appl) break;
5422       switch (pty_cai[5])
5423       {
5424         case DIVERSION_INTERROGATE_CFU:
5425         case DIVERSION_INTERROGATE_CFB:
5426         case DIVERSION_INTERROGATE_CFNR:
5427           dbug(1,dprintf("Interr_Div"));
5428           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5429           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430           break;
5431         case DIVERSION_INTERROGATE_NUM:
5432           dbug(1,dprintf("Interr_Num"));
5433           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5434           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5435           break;
5436         case CCBS_REQUEST:
5437           dbug(1,dprintf("CCBS Request"));
5438           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5439           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5440           break;
5441         case CCBS_DEACTIVATE:
5442           dbug(1,dprintf("CCBS Deactivate"));
5443           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5444           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5445           break;
5446         case CCBS_INTERROGATE:
5447           dbug(1,dprintf("CCBS Interrogate"));
5448           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5449           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5450           break;
5451       }
5452       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5453       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5454       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5455       plci_remove(plci);
5456       break;
5457
5458     case ACTIVATION_MWI:
5459     case DEACTIVATION_MWI:
5460       if(pty_cai[5]==ACTIVATION_MWI)
5461       {
5462         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5463       }
5464       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5465       if(plci->cr_enquiry)
5466       {
5467         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5468         plci_remove(plci);
5469       }
5470       else
5471       {
5472         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5473       }
5474       break;
5475     case MWI_INDICATION:
5476       if(pty_cai[0]>=0x12)
5477       {
5478         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5479         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5480         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5481         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5482         {
5483           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5484           {
5485             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5486             plci_remove(plci);
5487             return;
5488           }
5489           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5490           pty_cai[0]=0;
5491         }
5492         else
5493         {
5494           for(i=0; i<max_appl; i++)
5495           {                     
5496             if(a->Notification_Mask[i]&SMASK_MWI)
5497             {
5498               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5499               pty_cai[0]=0;
5500             }
5501           }
5502         }
5503
5504         if(!pty_cai[0])
5505         { /* acknowledge */
5506           facility[2]= 0; /* returncode */
5507         }
5508         else facility[2]= 0xff;
5509       }
5510       else
5511       {
5512         /* reject */
5513         facility[2]= 0xff; /* returncode */
5514       }
5515       facility[0]= 2;
5516       facility[1]= MWI_RESPONSE; /* Function */
5517       add_p(plci,CAI,facility);
5518       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5519       sig_req(plci,S_SERVICE,0);
5520       send_req(plci);
5521       plci->command = 0;
5522       next_internal_command (Id, plci);
5523       break;
5524     case CONF_ADD: /* OK */
5525     case CONF_BEGIN:
5526     case CONF_DROP:
5527     case CONF_ISOLATE:
5528     case CONF_REATTACH:
5529     case CONF_PARTYDISC:
5530       CONF_Ind[0]=9;
5531       CONF_Ind[3]=6;
5532       switch(pty_cai[5])
5533       {
5534       case CONF_BEGIN:
5535           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5536           if(pty_cai[0]==6)
5537           {
5538               d=pty_cai[6];
5539               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5540           }
5541           else
5542           {
5543               PUT_DWORD(&CONF_Ind[6],0x0);
5544           }
5545           break;
5546       case CONF_ISOLATE:
5547           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5548           CONF_Ind[0]=5;
5549           CONF_Ind[3]=2;
5550           break;
5551       case CONF_REATTACH:
5552           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5553           CONF_Ind[0]=5;
5554           CONF_Ind[3]=2;
5555           break;
5556       case CONF_DROP:
5557           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5558           CONF_Ind[0]=5;
5559           CONF_Ind[3]=2;
5560           break;
5561       case CONF_ADD:
5562           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5563           d=pty_cai[6];
5564           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5565           tplci=plci->relatedPTYPLCI;
5566           if(tplci) tplci->ptyState = CONNECTED;
5567           break;
5568       case CONF_PARTYDISC:
5569           CONF_Ind[0]=7;
5570           CONF_Ind[3]=4;          
5571           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5572           d=pty_cai[6];
5573           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5574           break;
5575       }
5576       plci->ptyState = CONNECTED;
5577       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5578       break;
5579     case CCBS_INFO_RETAIN:
5580     case CCBS_ERASECALLLINKAGEID:
5581     case CCBS_STOP_ALERTING:
5582       CONF_Ind[0]=5;
5583       CONF_Ind[3]=2;
5584       switch(pty_cai[5])
5585       {
5586       case CCBS_INFO_RETAIN:
5587         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5588         break;
5589       case CCBS_STOP_ALERTING:
5590         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5591     break;
5592       case CCBS_ERASECALLLINKAGEID:
5593         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5594         CONF_Ind[0]=7;
5595         CONF_Ind[3]=4;
5596         CONF_Ind[6]=0;
5597         CONF_Ind[7]=0;
5598         break;
5599       }      
5600       w=pty_cai[6];
5601       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5602
5603       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5604       {
5605         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5606       }
5607       else
5608       {
5609         for(i=0; i<max_appl; i++)
5610             if(a->Notification_Mask[i]&SMASK_CCBS)
5611                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5612       }
5613       break;
5614     }
5615     break;
5616   case CALL_HOLD_REJ:
5617     cau = parms[7];
5618     if(cau)
5619     {
5620       i = _L3_CAUSE | cau[2];
5621       if(cau[2]==0) i = 0x3603;
5622     }
5623     else
5624     {
5625       i = 0x3603;
5626     }
5627     PUT_WORD(&SS_Ind[1],S_HOLD);
5628     PUT_WORD(&SS_Ind[4],i);
5629     if(plci->SuppState == HOLD_REQUEST)
5630     {
5631       plci->SuppState = IDLE;
5632       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5633     }
5634     break;
5635
5636   case CALL_HOLD_ACK:
5637     if(plci->SuppState == HOLD_REQUEST)
5638     {
5639       plci->SuppState = CALL_HELD;
5640       CodecIdCheck(a, plci);
5641       start_internal_command (Id, plci, hold_save_command);
5642     }
5643     break;
5644
5645   case CALL_RETRIEVE_REJ:
5646     cau = parms[7];
5647     if(cau)
5648     {
5649       i = _L3_CAUSE | cau[2];
5650       if(cau[2]==0) i = 0x3603;
5651     }
5652     else
5653     {
5654       i = 0x3603;
5655     }
5656     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5657     PUT_WORD(&SS_Ind[4],i);
5658     if(plci->SuppState == RETRIEVE_REQUEST)
5659     {
5660       plci->SuppState = CALL_HELD;
5661       CodecIdCheck(a, plci);
5662       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5663     }
5664     break;
5665
5666   case CALL_RETRIEVE_ACK:
5667     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5668     if(plci->SuppState == RETRIEVE_REQUEST)
5669     {
5670       plci->SuppState = IDLE;
5671       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5672       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5673       if(plci->tel)
5674       {
5675         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5676         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5677         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5678         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5679         {
5680           dbug(1,dprintf("Get B-ch"));
5681           start_internal_command (Id, plci, retrieve_restore_command);
5682         }
5683         else
5684           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5685       }
5686       else
5687         start_internal_command (Id, plci, retrieve_restore_command);
5688     }
5689     break;
5690
5691   case INDICATE_IND:
5692     if(plci->State != LISTENING) {
5693       sig_req(plci,HANGUP,0);
5694       send_req(plci);
5695       break;
5696     }
5697     cip = find_cip(a,parms[4],parms[6]);
5698     cip_mask = 1L<<cip;
5699     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5700     clear_c_ind_mask (plci);
5701     if (!remove_started && !a->adapter_disabled)
5702     {
5703       set_c_ind_mask_bit (plci, MAX_APPL);
5704       group_optimization(a, plci);
5705       for(i=0; i<max_appl; i++) {
5706         if(application[i].Id
5707         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5708         && CPN_filter_ok(parms[0],a,i)
5709         && test_group_ind_mask_bit (plci, i) ) {
5710           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5711           set_c_ind_mask_bit (plci, i);
5712           dump_c_ind_mask (plci);
5713           plci->State = INC_CON_PENDING;
5714           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5715             CALL_DIR_IN | CALL_DIR_ANSWER;
5716           if(esc_chi[0]) {
5717             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5718             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5719           }
5720           /* if a listen on the ext controller is done, check if hook states */
5721           /* are supported or if just a on board codec must be activated     */
5722           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5723             if(a->profile.Global_Options & HANDSET)
5724               plci->tel = ADV_VOICE;
5725             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5726               plci->tel = CODEC;
5727             if(plci->tel) Id|=EXT_CONTROLLER;
5728             a->codec_listen[i] = plci;
5729           }
5730
5731           sendf(&application[i],_CONNECT_I,Id,0,
5732                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5733                              parms[0],    /* CalledPartyNumber   */
5734                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5735                              parms[2],    /* CalledPartySubad    */
5736                              parms[3],    /* CallingPartySubad   */
5737                              parms[4],    /* BearerCapability    */
5738                              parms[5],    /* LowLC               */
5739                              parms[6],    /* HighLC              */
5740                              ai_len,      /* nested struct add_i */
5741                              add_i[0],    /* B channel info    */
5742                              add_i[1],    /* keypad facility   */
5743                              add_i[2],    /* user user data    */
5744                              add_i[3],    /* nested facility   */
5745                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5746                              );
5747           SendSSExtInd(&application[i],
5748                         plci,
5749                         Id,
5750                         multi_ssext_parms);
5751           SendSetupInfo(&application[i],
5752                         plci,
5753                         Id,
5754                         parms,
5755                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5756         }
5757       }
5758       clear_c_ind_mask_bit (plci, MAX_APPL);
5759       dump_c_ind_mask (plci);
5760     }
5761     if(c_ind_mask_empty (plci)) {
5762       sig_req(plci,HANGUP,0);
5763       send_req(plci);
5764       plci->State = IDLE;
5765     }
5766     plci->notifiedcall = 0;
5767     a->listen_active--;
5768     listen_check(a);
5769     break;
5770
5771   case CALL_PEND_NOTIFY:
5772     plci->notifiedcall = 1;
5773     listen_check(a);
5774     break;
5775
5776   case CALL_IND:
5777   case CALL_CON:
5778     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5779     {
5780       if(plci->internal_command==PERM_COD_CONN_PEND)
5781       {
5782         if(plci->State==ADVANCED_VOICE_NOSIG)
5783         {
5784           dbug(1,dprintf("***Codec OK"));
5785           if(a->AdvSignalPLCI)
5786           {
5787             tplci = a->AdvSignalPLCI;
5788             if(tplci->spoofed_msg)
5789             {
5790               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5791               tplci->command = 0;
5792               tplci->internal_command = 0;
5793               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5794               switch (tplci->spoofed_msg)
5795               {
5796               case CALL_RES:
5797                 tplci->command = _CONNECT_I|RESPONSE;
5798                 api_load_msg (&tplci->saved_msg, saved_parms);
5799                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5800                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5801                 {
5802                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5803                   add_p(tplci,LLI,"\x01\x01");
5804                 }
5805                 add_s(tplci, CONN_NR, &saved_parms[2]);
5806                 add_s(tplci, LLC, &saved_parms[4]);
5807                 add_ai(tplci, &saved_parms[5]);
5808                 tplci->State = INC_CON_ACCEPT;
5809                 sig_req(tplci, CALL_RES,0);
5810                 send_req(tplci);
5811                 break;
5812
5813               case AWAITING_SELECT_B:
5814                 dbug(1,dprintf("Select_B continue"));
5815                 start_internal_command (x_Id, tplci, select_b_command);
5816                 break;
5817
5818               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5819                 if(!tplci->Sig.Id)
5820                 {
5821                   dbug(1,dprintf("No SigID!"));
5822                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5823                   plci_remove(tplci);
5824                   break;
5825                 }
5826                 tplci->command = _MANUFACTURER_R;
5827                 api_load_msg (&tplci->saved_msg, saved_parms);
5828                 dir = saved_parms[2].info[0];
5829                 if(dir==1) {
5830                   sig_req(tplci,CALL_REQ,0);
5831                 }
5832                 else if(!dir){
5833                   sig_req(tplci,LISTEN_REQ,0);
5834                 }
5835                 send_req(tplci);
5836                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5837                 break;
5838
5839               case (CALL_REQ|AWAITING_MANUF_CON):
5840                 sig_req(tplci,CALL_REQ,0);
5841                 send_req(tplci);
5842                 break;
5843
5844               case CALL_REQ:
5845                 if(!tplci->Sig.Id)
5846                 {
5847                   dbug(1,dprintf("No SigID!"));
5848                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5849                   plci_remove(tplci);
5850                   break;
5851                 }
5852                 tplci->command = _CONNECT_R;
5853                 api_load_msg (&tplci->saved_msg, saved_parms);
5854                 add_s(tplci,CPN,&saved_parms[1]);
5855                 add_s(tplci,DSA,&saved_parms[3]);
5856                 add_ai(tplci,&saved_parms[9]);
5857                 sig_req(tplci,CALL_REQ,0);
5858                 send_req(tplci);
5859                 break;
5860
5861               case CALL_RETRIEVE:
5862                 tplci->command = C_RETRIEVE_REQ;
5863                 sig_req(tplci,CALL_RETRIEVE,0);
5864                 send_req(tplci);
5865                 break;
5866               }
5867               tplci->spoofed_msg = 0;
5868               if (tplci->internal_command == 0)
5869                 next_internal_command (x_Id, tplci);
5870             }
5871           }
5872           next_internal_command (Id, plci);
5873           break;
5874         }
5875         dbug(1,dprintf("***Codec Hook Init Req"));
5876         plci->internal_command = PERM_COD_HOOK;
5877         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5878         sig_req(plci,TEL_CTRL,0);
5879         send_req(plci);
5880       }
5881     }
5882     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5883     && plci->State!=INC_ACT_PENDING)
5884     {
5885       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5886       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5887       {
5888         chi[2] = plci->b_channel;
5889         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5890       }
5891       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5892       plci->State = INC_ACT_PENDING;
5893     }
5894     break;
5895
5896   case TEL_CTRL:
5897     Number = 0;
5898     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5899     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5900       switch (ie[1]&0x91) {
5901         case 0x80:   /* hook off */
5902         case 0x81:
5903           if(plci->internal_command==PERM_COD_HOOK)
5904           {
5905             dbug(1,dprintf("init:hook_off"));
5906             plci->hook_state = ie[1];
5907             next_internal_command (Id, plci);
5908             break;
5909           }
5910           else /* ignore doubled hook indications */
5911           {
5912             if( ((plci->hook_state)&0xf0)==0x80)
5913             {
5914               dbug(1,dprintf("ignore hook"));
5915               break;
5916             }
5917             plci->hook_state = ie[1]&0x91;
5918           }
5919           /* check for incoming call pending */
5920           /* and signal '+'.Appl must decide */
5921           /* with connect_res if call must   */
5922           /* accepted or not                 */
5923           for(i=0, tplci=NULL;i<max_appl;i++){
5924             if(a->codec_listen[i]
5925             && (a->codec_listen[i]->State==INC_CON_PENDING
5926               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5927               tplci = a->codec_listen[i];
5928               tplci->appl = &application[i];
5929             }
5930           }
5931           /* no incoming call, do outgoing call */
5932           /* and signal '+' if outg. setup   */
5933           if(!a->AdvSignalPLCI && !tplci){
5934             if((i=get_plci(a))) {
5935               a->AdvSignalPLCI = &a->plci[i-1];
5936               tplci = a->AdvSignalPLCI;
5937               tplci->tel  = ADV_VOICE;
5938               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5939               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5940                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5941                 add_p(tplci,LLI,"\x01\x01");
5942               }
5943               add_p(tplci, CAI, voice_cai);
5944               add_p(tplci, OAD, a->TelOAD);
5945               add_p(tplci, OSA, a->TelOSA);
5946               add_p(tplci,SHIFT|6,NULL);
5947               add_p(tplci,SIN,"\x02\x01\x00");
5948               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5949               sig_req(tplci,ASSIGN,DSIG_ID);
5950               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5951               a->AdvSignalPLCI->command = 0;
5952               tplci->appl = a->AdvSignalAppl;
5953               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5954               send_req(tplci);
5955             }
5956
5957           }
5958
5959           if(!tplci) break;
5960           Id = ((word)tplci->Id<<8)|a->Id;
5961           Id|=EXT_CONTROLLER;
5962           sendf(tplci->appl,
5963                 _FACILITY_I,
5964                 Id,
5965                 0,
5966                 "ws", (word)0, "\x01+");
5967           break;
5968
5969         case 0x90:   /* hook on  */
5970         case 0x91:
5971           if(plci->internal_command==PERM_COD_HOOK)
5972           {
5973             dbug(1,dprintf("init:hook_on"));
5974             plci->hook_state = ie[1]&0x91;
5975             next_internal_command (Id, plci);
5976             break;
5977           }
5978           else /* ignore doubled hook indications */
5979           {
5980             if( ((plci->hook_state)&0xf0)==0x90) break;
5981             plci->hook_state = ie[1]&0x91;
5982           }
5983           /* hangup the adv. voice call and signal '-' to the appl */
5984           if(a->AdvSignalPLCI) {
5985             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5986             if(plci->tel) Id|=EXT_CONTROLLER;
5987             sendf(a->AdvSignalAppl,
5988                   _FACILITY_I,
5989                   Id,
5990                   0,
5991                   "ws", (word)0, "\x01-");
5992             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5993             a->AdvSignalPLCI->command = 0;
5994             sig_req(a->AdvSignalPLCI,HANGUP,0);
5995             send_req(a->AdvSignalPLCI);
5996           }
5997           break;
5998       }
5999     }
6000     break;
6001
6002   case RESUME:
6003     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
6004     PUT_WORD(&resume_cau[4],GOOD);
6005     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6006     break;
6007
6008   case SUSPEND:
6009     clear_c_ind_mask (plci);
6010
6011     if (plci->NL.Id && !plci->nl_remove_id) {
6012       mixer_remove (plci);
6013       nl_req_ncci(plci,REMOVE,0);
6014     }
6015     if (!plci->sig_remove_id) {
6016       plci->internal_command = 0;
6017       sig_req(plci,REMOVE,0);
6018     }
6019     send_req(plci);
6020     if(!plci->channels) {
6021       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6022       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6023     }
6024     break;
6025
6026   case SUSPEND_REJ:
6027     break;
6028
6029   case HANGUP:
6030     plci->hangup_flow_ctrl_timer=0;
6031     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6032     cau = parms[7];
6033     if(cau) {
6034       i = _L3_CAUSE | cau[2];
6035       if(cau[2]==0) i = 0;
6036       else if(cau[2]==8) i = _L1_ERROR;
6037       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6038       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6039     }
6040     else {
6041       i = _L3_ERROR;
6042     }
6043
6044     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6045     {
6046       for(i=0; i<max_appl; i++)
6047       {
6048         if(test_c_ind_mask_bit (plci, i))
6049           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6050       }
6051     }
6052     else
6053     {
6054       clear_c_ind_mask (plci);
6055     }
6056     if(!plci->appl)
6057     {
6058       if (plci->State == LISTENING)
6059       {
6060         plci->notifiedcall=0;
6061         a->listen_active--;
6062       }
6063       plci->State = INC_DIS_PENDING;
6064       if(c_ind_mask_empty (plci))
6065       {
6066         plci->State = IDLE;
6067         if (plci->NL.Id && !plci->nl_remove_id)
6068         {
6069           mixer_remove (plci);
6070           nl_req_ncci(plci,REMOVE,0);
6071         }
6072         if (!plci->sig_remove_id)
6073         {
6074           plci->internal_command = 0;
6075           sig_req(plci,REMOVE,0);
6076         }
6077         send_req(plci);
6078       }
6079     }
6080     else
6081     {
6082         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6083         /* result in a second HANGUP! Don't generate another        */
6084         /* DISCONNECT                                               */
6085       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6086       {
6087         if(plci->State==RESUMING)
6088         {
6089           PUT_WORD(&resume_cau[4],i);
6090           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6091         }
6092         plci->State = INC_DIS_PENDING;
6093         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6094       }
6095     }
6096     break;
6097
6098   case SSEXT_IND:
6099     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6100     break;
6101
6102   case VSWITCH_REQ:
6103     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6104     break;
6105   case VSWITCH_IND:
6106  if(plci->relatedPTYPLCI &&
6107   plci->vswitchstate==3 &&
6108   plci->relatedPTYPLCI->vswitchstate==3 &&
6109   parms[MAXPARMSIDS-1][0])
6110  {
6111   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6112   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6113   send_req(plci->relatedPTYPLCI);
6114  }
6115     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6116     break;
6117
6118   }
6119 }
6120
6121
6122 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6123 {
6124   word i;
6125   byte   * ie;
6126   word Info_Number;
6127   byte   * Info_Element;
6128   word Info_Mask = 0;
6129
6130   dbug(1,dprintf("SetupInfo"));
6131
6132   for(i=0; i<MAXPARMSIDS; i++) {
6133     ie = parms[i];
6134     Info_Number = 0;
6135     Info_Element = ie;
6136     if(ie[0]) {
6137       switch(i) {
6138       case 0:
6139         dbug(1,dprintf("CPN "));
6140         Info_Number = 0x0070;
6141         Info_Mask   = 0x80;
6142         Info_Sent_Flag = true;
6143         break;
6144       case 8:  /* display      */
6145         dbug(1,dprintf("display(%d)",i));
6146         Info_Number = 0x0028;
6147         Info_Mask = 0x04;
6148         Info_Sent_Flag = true;
6149         break;
6150       case 16: /* Channel Id */
6151         dbug(1,dprintf("CHI"));
6152         Info_Number = 0x0018;
6153         Info_Mask = 0x100;
6154         Info_Sent_Flag = true;
6155         mixer_set_bchannel_id (plci, Info_Element);
6156         break;
6157       case 19: /* Redirected Number */
6158         dbug(1,dprintf("RDN"));
6159         Info_Number = 0x0074;
6160         Info_Mask = 0x400;
6161         Info_Sent_Flag = true;
6162         break;
6163       case 20: /* Redirected Number extended */
6164         dbug(1,dprintf("RDX"));
6165         Info_Number = 0x0073;
6166         Info_Mask = 0x400;
6167         Info_Sent_Flag = true;
6168         break;
6169       case 22: /* Redirecing Number  */
6170         dbug(1,dprintf("RIN"));
6171         Info_Number = 0x0076;
6172         Info_Mask = 0x400;
6173         Info_Sent_Flag = true;
6174         break;
6175       default:
6176         Info_Number = 0;
6177         break;
6178       }
6179     }
6180
6181     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6182       Info_Number = 0x8000 |5;
6183       Info_Mask = 0x10;
6184       Info_Element = "";
6185     }
6186
6187     if(Info_Sent_Flag && Info_Number){
6188       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6189         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6190       }
6191     }
6192   }
6193 }
6194
6195
6196 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6197 {
6198   word i;
6199   word j;
6200   word k;
6201   byte   * ie;
6202   word Info_Number;
6203   byte   * Info_Element;
6204   word Info_Mask = 0;
6205   static byte charges[5] = {4,0,0,0,0};
6206   static byte cause[] = {0x02,0x80,0x00};
6207   APPL   *appl;
6208
6209   dbug(1,dprintf("InfoParse "));
6210
6211   if(
6212         !plci->appl
6213         && !plci->State
6214         && plci->Sig.Ind!=NCR_FACILITY
6215       )
6216   {
6217     dbug(1,dprintf("NoParse "));
6218     return;
6219   }
6220   cause[2] = 0;
6221   for(i=0; i<MAXPARMSIDS; i++) {
6222     ie = parms[i];
6223     Info_Number = 0;
6224     Info_Element = ie;
6225     if(ie[0]) {
6226       switch(i) {
6227       case 0:
6228         dbug(1,dprintf("CPN "));
6229         Info_Number = 0x0070;
6230         Info_Mask   = 0x80;
6231         break;
6232       case 7: /* ESC_CAU */
6233         dbug(1,dprintf("cau(0x%x)",ie[2]));
6234         Info_Number = 0x0008;
6235         Info_Mask = 0x00;
6236         cause[2] = ie[2];
6237         Info_Element = NULL;
6238         break;
6239       case 8:  /* display      */
6240         dbug(1,dprintf("display(%d)",i));
6241         Info_Number = 0x0028;
6242         Info_Mask = 0x04;
6243         break;
6244       case 9:  /* Date display */
6245         dbug(1,dprintf("date(%d)",i));
6246         Info_Number = 0x0029;
6247         Info_Mask = 0x02;
6248         break;
6249       case 10: /* charges */
6250         for(j=0;j<4;j++) charges[1+j] = 0;
6251         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6252         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6253         Info_Number = 0x4000;
6254         Info_Mask = 0x40;
6255         Info_Element = charges;
6256         break;
6257       case 11: /* user user info */
6258         dbug(1,dprintf("uui"));
6259         Info_Number = 0x007E;
6260         Info_Mask = 0x08;
6261         break;
6262       case 12: /* congestion receiver ready */
6263         dbug(1,dprintf("clRDY"));
6264         Info_Number = 0x00B0;
6265         Info_Mask = 0x08;
6266         Info_Element = "";
6267         break;
6268       case 13: /* congestion receiver not ready */
6269         dbug(1,dprintf("clNRDY"));
6270         Info_Number = 0x00BF;
6271         Info_Mask = 0x08;
6272         Info_Element = "";
6273         break;
6274       case 15: /* Keypad Facility */
6275         dbug(1,dprintf("KEY"));
6276         Info_Number = 0x002C;
6277         Info_Mask = 0x20;
6278         break;
6279       case 16: /* Channel Id */
6280         dbug(1,dprintf("CHI"));
6281         Info_Number = 0x0018;
6282         Info_Mask = 0x100;
6283         mixer_set_bchannel_id (plci, Info_Element);
6284         break;
6285       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6286         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6287         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6288         Info_Number = 0x0008;
6289         Info_Mask = 0x01;
6290         if(cause[2] != ie[2]) Info_Element = cause;
6291         break;
6292       case 19: /* Redirected Number */
6293         dbug(1,dprintf("RDN"));
6294         Info_Number = 0x0074;
6295         Info_Mask = 0x400;
6296         break;
6297       case 22: /* Redirecing Number  */
6298         dbug(1,dprintf("RIN"));
6299         Info_Number = 0x0076;
6300         Info_Mask = 0x400;
6301         break;
6302       case 23: /* Notification Indicator  */
6303         dbug(1,dprintf("NI"));
6304         Info_Number = (word)NI;
6305         Info_Mask = 0x210;
6306         break;
6307       case 26: /* Call State  */
6308         dbug(1,dprintf("CST"));
6309         Info_Number = (word)CST;
6310         Info_Mask = 0x01; /* do with cause i.e. for now */
6311         break;
6312       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6313         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6314         Info_Number = 0x8000 |ie[3];
6315         if(iesent) Info_Mask = 0xffff;
6316         else  Info_Mask = 0x10;
6317         Info_Element = "";
6318         break;
6319       default:
6320         Info_Number  = 0;
6321         Info_Mask    = 0;
6322         Info_Element = "";
6323         break;
6324       }
6325     }
6326
6327     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6328     {
6329       for(j=0; j<max_appl; j++)
6330       {
6331         appl = &application[j];
6332         if(Info_Number
6333         && appl->Id
6334         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6335         {
6336           dbug(1,dprintf("NCR_Ind"));
6337           iesent=true;
6338           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6339         }
6340       }
6341     }
6342     else if(!plci->appl)
6343     { /* overlap receiving broadcast */
6344       if(Info_Number==CPN
6345       || Info_Number==KEY
6346       || Info_Number==NI
6347       || Info_Number==DSP
6348       || Info_Number==UUI )
6349       {
6350         for(j=0; j<max_appl; j++)
6351         {
6352           if(test_c_ind_mask_bit (plci, j))
6353           {
6354             dbug(1,dprintf("Ovl_Ind"));
6355             iesent=true;
6356             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6357           }
6358         }
6359       }
6360     }               /* all other signalling states */
6361     else if(Info_Number
6362     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6363     {
6364       dbug(1,dprintf("Std_Ind"));
6365       iesent=true;
6366       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6367     }
6368   }
6369 }
6370
6371
6372 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6373                         dword info_mask, byte setupParse)
6374 {
6375   word i;
6376   word j;
6377   byte   * ie;
6378   word Info_Number;
6379   byte   * Info_Element;
6380   APPL   *appl;
6381   word Info_Mask = 0;
6382   byte iesent=0;
6383
6384   if(
6385       !plci->appl
6386       && !plci->State
6387       && plci->Sig.Ind!=NCR_FACILITY
6388       && !setupParse
6389       )
6390   {
6391     dbug(1,dprintf("NoM-IEParse "));
6392     return 0;
6393   }
6394   dbug(1,dprintf("M-IEParse "));
6395
6396   for(i=0; i<MAX_MULTI_IE; i++)
6397   {
6398     ie = parms[i];
6399     Info_Number = 0;
6400     Info_Element = ie;
6401     if(ie[0])
6402     {
6403       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6404       Info_Number = (word)ie_type;
6405       Info_Mask = (word)info_mask;
6406     }
6407
6408     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6409     {
6410       for(j=0; j<max_appl; j++)
6411       {
6412         appl = &application[j];
6413         if(Info_Number
6414         && appl->Id
6415         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6416         {
6417           iesent = true;
6418           dbug(1,dprintf("Mlt_NCR_Ind"));
6419           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6420         }
6421       }
6422     }
6423     else if(!plci->appl && Info_Number)
6424     {                                        /* overlap receiving broadcast */
6425       for(j=0; j<max_appl; j++)
6426       {
6427         if(test_c_ind_mask_bit (plci, j))
6428         {
6429           iesent = true;
6430           dbug(1,dprintf("Mlt_Ovl_Ind"));
6431           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6432         }
6433       }
6434     }                                        /* all other signalling states */
6435     else if(Info_Number
6436     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6437     {
6438       iesent = true;
6439       dbug(1,dprintf("Mlt_Std_Ind"));
6440       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6441     }
6442   }
6443   return iesent;
6444 }
6445
6446 static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6447 {
6448   word i;
6449    /* Format of multi_ssext_parms[i][]:
6450    0 byte length
6451    1 byte SSEXTIE
6452    2 byte SSEXT_REQ/SSEXT_IND
6453    3 byte length
6454    4 word SSExtCommand
6455    6... Params
6456    */
6457   if(
6458    plci
6459    && plci->State
6460    && plci->Sig.Ind!=NCR_FACILITY
6461     )
6462  for(i=0;i<MAX_MULTI_IE;i++)
6463     {
6464       if(parms[i][0]<6) continue;
6465    if(parms[i][2]==SSEXT_REQ) continue;
6466
6467    if(appl)
6468    {
6469     parms[i][0]=0; /* kill it */
6470     sendf(appl,_MANUFACTURER_I,
6471     Id,
6472     0,
6473     "dwS",
6474     _DI_MANU_ID,
6475     _DI_SSEXT_CTRL,
6476     &parms[i][3]);
6477    }
6478    else if(plci->appl)
6479    {
6480     parms[i][0]=0; /* kill it */
6481     sendf(plci->appl,_MANUFACTURER_I,
6482     Id,
6483     0,
6484     "dwS",
6485     _DI_MANU_ID,
6486     _DI_SSEXT_CTRL,
6487     &parms[i][3]);
6488    }
6489     }
6490 };
6491
6492 static void nl_ind(PLCI *plci)
6493 {
6494   byte ch;
6495   word ncci;
6496   dword Id;
6497   DIVA_CAPI_ADAPTER   * a;
6498   word NCCIcode;
6499   APPL   * APPLptr;
6500   word count;
6501   word Num;
6502   word i, ncpi_state;
6503   byte len, ncci_state;
6504   word msg;
6505   word info = 0;
6506   word fax_feature_bits;
6507   byte fax_send_edata_ack;
6508   static byte v120_header_buffer[2 + 3];
6509   static word fax_info[] = {
6510     0,                     /* T30_SUCCESS                        */
6511     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6512     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6513     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6514     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6516     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6517     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6518     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6519     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6520     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6521     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6522     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6523     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6524     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6525     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6526     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6527     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6528     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6529     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6530     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6531     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6532     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6533     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6534     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6535     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6536     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6537     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6538     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6539     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6540     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6541     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6542     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6543     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6544     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6545     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6546     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6547     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6548     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6549     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6550     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6551     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6552     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6553     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6554     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6555     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6556     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6557   };
6558
6559     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6560
6561
6562   static word rtp_info[] = {
6563     GOOD,                  /* RTP_SUCCESS                       */
6564     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6565   };
6566
6567   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6568   {
6569     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6570     0x00000000, 0x00000000, 0x00000000, 0x00000000
6571   };
6572
6573   ch = plci->NL.IndCh;
6574   a = plci->adapter;
6575   ncci = a->ch_ncci[ch];
6576   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6577   if(plci->tel) Id|=EXT_CONTROLLER;
6578   APPLptr = plci->appl;
6579   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",
6580     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6581
6582   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6583
6584   if (plci->nl_remove_id)
6585   {
6586     plci->NL.RNR = 2; /* discard */
6587     dbug(1,dprintf("NL discard while remove pending"));
6588     return;
6589   }
6590   if((plci->NL.Ind &0x0f)==N_CONNECT)
6591   {
6592     if(plci->State==INC_DIS_PENDING
6593     || plci->State==OUTG_DIS_PENDING
6594     || plci->State==IDLE)
6595     {
6596       plci->NL.RNR = 2; /* discard */
6597       dbug(1,dprintf("discard n_connect"));
6598       return;
6599     }
6600     if(plci->State < INC_ACT_PENDING)
6601     {
6602       plci->NL.RNR = 1; /* flow control */
6603       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6604       return;
6605     }
6606   }
6607
6608   if(!APPLptr)                         /* no application or invalid data */
6609   {                                    /* while reloading the DSP        */
6610     dbug(1,dprintf("discard1"));
6611     plci->NL.RNR = 2;
6612     return;
6613   }
6614
6615   if (((plci->NL.Ind &0x0f) == N_UDATA)
6616      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6617         || (plci->B2_prot == 7)
6618         || (plci->B3_prot == 7)) )
6619   {
6620     plci->ncpi_buffer[0] = 0;
6621
6622     ncpi_state = plci->ncpi_state;
6623     if (plci->NL.complete == 1)
6624     {
6625       byte  * data = &plci->NL.RBuffer->P[0];
6626
6627       if ((plci->NL.RBuffer->length >= 12)
6628         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6629           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6630       {
6631         word conn_opt, ncpi_opt = 0x00;
6632 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6633
6634         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6635           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6636         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6637           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6638
6639         data++;    /* indication code */
6640         data += 2; /* timestamp */
6641         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6642           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6643         data++;    /* connected norm */
6644         conn_opt = GET_WORD(data);
6645         data += 2; /* connected options */
6646
6647         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6648
6649         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6650         {
6651           ncpi_opt |= MDM_NCPI_ECM_V42;
6652         }
6653         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6654         {
6655           ncpi_opt |= MDM_NCPI_ECM_MNP;
6656         }
6657         else
6658         {
6659           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6660         }
6661         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6662         {
6663           ncpi_opt |= MDM_NCPI_COMPRESSED;
6664         }
6665         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6666         plci->ncpi_buffer[0] = 4;
6667
6668         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6669       }
6670     }
6671     if (plci->B3_prot == 7)
6672     {
6673       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6674        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6675        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6676       {
6677         a->ncci_state[ncci] = INC_ACT_PENDING;
6678         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6679         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6680       }
6681     }
6682
6683     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6684         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6685      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6686      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6687
6688     {
6689       plci->NL.RNR = 2;
6690       return;
6691     }
6692   }
6693
6694   if(plci->NL.complete == 2)
6695     {
6696     if (((plci->NL.Ind &0x0f) == N_UDATA)
6697      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6698     {
6699       switch(plci->RData[0].P[0])
6700       {
6701
6702       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6703         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6705         break;
6706       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6707         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6708           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6709         break;
6710       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6711         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6712         break;
6713       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6714         dtmf_confirmation (Id, plci);
6715         break;
6716
6717
6718       case UDATA_INDICATION_MIXER_TAP_DATA:
6719         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6720  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6721  if (i != 0)
6722  {
6723    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6724           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6725  }
6726         break;
6727
6728
6729       case UDATA_INDICATION_MIXER_COEFS_SET:
6730         mixer_indication_coefs_set (Id, plci);
6731         break;
6732       case UDATA_INDICATION_XCONNECT_FROM:
6733         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6734         break;
6735       case UDATA_INDICATION_XCONNECT_TO:
6736         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6737         break;
6738
6739
6740       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6741         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6742         break;
6743
6744
6745
6746       default:
6747         break;
6748       }
6749     }
6750     else
6751   {
6752       if ((plci->RData[0].PLength != 0)
6753      && ((plci->B2_prot == B2_V120_ASYNC)
6754       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6755       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6756     {
6757
6758       sendf(plci->appl,_DATA_B3_I,Id,0,
6759             "dwww",
6760             plci->RData[1].P,
6761               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6762             plci->RNum,
6763             plci->RFlags);
6764
6765     }
6766     else
6767     {
6768
6769       sendf(plci->appl,_DATA_B3_I,Id,0,
6770             "dwww",
6771             plci->RData[0].P,
6772             plci->RData[0].PLength,
6773             plci->RNum,
6774             plci->RFlags);
6775
6776     }
6777     }
6778     return;
6779   }
6780
6781   fax_feature_bits = 0;
6782   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6783      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6784      (plci->NL.Ind &0x0f)==N_DISC ||
6785      (plci->NL.Ind &0x0f)==N_EDATA ||
6786      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6787   {
6788     info = 0;
6789     plci->ncpi_buffer[0] = 0;
6790     switch (plci->B3_prot) {
6791     case  0: /*XPARENT*/
6792     case  1: /*T.90 NL*/
6793       break;    /* no network control protocol info - jfr */
6794     case  2: /*ISO8202*/
6795     case  3: /*X25 DCE*/
6796       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6797       plci->ncpi_buffer[0] = (byte)(i+3);
6798       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6799       plci->ncpi_buffer[2] = 0;
6800       plci->ncpi_buffer[3] = 0;
6801       break;
6802     case  4: /*T.30 - FAX*/
6803     case  5: /*T.30 - FAX*/
6804       if(plci->NL.RLength>=sizeof(T30_INFO))
6805       {
6806         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6807         len = 9;
6808         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6809         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6810         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6811         if (plci->B3_prot == 5)
6812         {
6813           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6814             i |= 0x8000; /* This is not an ECM connection */
6815           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6816             i |= 0x4000; /* This is a connection with MMR compression */
6817           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6818             i |= 0x2000; /* This is a connection with MR compression */
6819           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6820             i |= 0x0004; /* More documents */
6821           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6822             i |= 0x0002; /* Fax-polling indication */
6823         }
6824         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6825         PUT_WORD(&(plci->ncpi_buffer[3]),i);
6826         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6827         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6828         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6829         plci->ncpi_buffer[len] = 0;
6830         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6831         {
6832           plci->ncpi_buffer[len] = 20;
6833           for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6834             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6835         }
6836         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6837         {
6838           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6839             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6840           else
6841             info = _FAX_PROTOCOL_ERROR;
6842         }
6843
6844         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6845           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6846         {
6847           i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6848           while (i < plci->NL.RBuffer->length)
6849             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6850         }
6851
6852         plci->ncpi_buffer[0] = len;
6853         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6854         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6855
6856         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6857  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6858          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6859           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6860          || (((plci->NL.Ind &0x0f) == N_EDATA)
6861           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6862            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6863            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6864  {
6865           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6866  }
6867  if (((plci->NL.Ind &0x0f) == N_DISC)
6868   || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6869   || (((plci->NL.Ind &0x0f) == N_EDATA)
6870    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6871  {
6872           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6873  }
6874       }
6875       break;
6876
6877     case B3_RTP:
6878       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6879       {
6880         if (plci->NL.RLength != 0)
6881         {
6882           info = rtp_info[plci->NL.RBuffer->P[0]];
6883           plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6884           for (i = 1; i < plci->NL.RLength; i++)
6885             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6886         }
6887       }
6888       break;
6889
6890     }
6891     plci->NL.RNR = 2;
6892   }
6893   switch(plci->NL.Ind &0x0f) {
6894   case N_EDATA:
6895     if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6896     {
6897       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6898         ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6899       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6900
6901       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6902        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6903        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6904        && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6905        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6906        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6907       {
6908         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6909         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6910           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6911         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6912  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6913    fax_send_edata_ack = false;
6914       }
6915
6916       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6917       {
6918         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6919         {
6920         case EDATA_T30_DIS:
6921           if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6922            && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6923            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6924            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6925           {
6926             a->ncci_state[ncci] = INC_ACT_PENDING;
6927             if (plci->B3_prot == 4)
6928               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6929             else
6930               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6931             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6932           }
6933           break;
6934
6935         case EDATA_T30_TRAIN_OK:
6936           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6937            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6938            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6939           {
6940             if (plci->B3_prot == 4)
6941               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6942             else
6943               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6944             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6945           }
6946           break;
6947
6948         case EDATA_T30_EOP_CAPI:
6949           if (a->ncci_state[ncci] == CONNECTED)
6950           {
6951             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6952             a->ncci_state[ncci] = INC_DIS_PENDING;
6953             plci->ncpi_state = 0;
6954      fax_send_edata_ack = false;
6955           }
6956           break;
6957         }
6958       }
6959       else
6960       {
6961         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6962         {
6963         case EDATA_T30_TRAIN_OK:
6964           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6965            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6966            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6967           {
6968             if (plci->B3_prot == 4)
6969               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6970             else
6971               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6972             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6973           }
6974           break;
6975         }
6976       }
6977       if (fax_send_edata_ack)
6978       {
6979         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6980  plci->fax_edata_ack_length = 1;
6981         start_internal_command (Id, plci, fax_edata_ack_command);
6982       }
6983     }
6984     else
6985     {
6986       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6987     }
6988     break;
6989   case N_CONNECT:
6990     if (!a->ch_ncci[ch])
6991     {
6992       ncci = get_ncci (plci, ch, 0);
6993       Id = (Id & 0xffff) | (((dword) ncci) << 16);
6994     }
6995     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6996       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6997
6998     msg = _CONNECT_B3_I;
6999     if (a->ncci_state[ncci] == IDLE)
7000       plci->channels++;
7001     else if (plci->B3_prot == 1)
7002       msg = _CONNECT_B3_T90_ACTIVE_I;
7003
7004     a->ncci_state[ncci] = INC_CON_PENDING;
7005     if(plci->B3_prot == 4)
7006       sendf(plci->appl,msg,Id,0,"s","");
7007     else
7008       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7009     break;
7010   case N_CONNECT_ACK:
7011     dbug(1,dprintf("N_connect_Ack"));
7012     if (plci->internal_command_queue[0]
7013      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7014       || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7015       || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7016     {
7017       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7018       if (!plci->internal_command)
7019         next_internal_command (Id, plci);
7020       break;
7021     }
7022     msg = _CONNECT_B3_ACTIVE_I;
7023     if (plci->B3_prot == 1)
7024     {
7025       if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7026         msg = _CONNECT_B3_T90_ACTIVE_I;
7027       a->ncci_state[ncci] = INC_ACT_PENDING;
7028       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7029     }
7030     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7031     {
7032       if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7033        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7034        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7035       {
7036         a->ncci_state[ncci] = INC_ACT_PENDING;
7037         if (plci->B3_prot == 4)
7038           sendf(plci->appl,msg,Id,0,"s","");
7039         else
7040           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7041         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7042       }
7043     }
7044     else
7045     {
7046       a->ncci_state[ncci] = INC_ACT_PENDING;
7047       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7048     }
7049     if (plci->adjust_b_restore)
7050     {
7051       plci->adjust_b_restore = false;
7052       start_internal_command (Id, plci, adjust_b_restore);
7053     }
7054     break;
7055   case N_DISC:
7056   case N_DISC_ACK:
7057     if (plci->internal_command_queue[0]
7058      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7059       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7060       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7061     {
7062       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7063       if (!plci->internal_command)
7064         next_internal_command (Id, plci);
7065     }
7066     ncci_state = a->ncci_state[ncci];
7067     ncci_remove (plci, ncci, false);
7068
7069         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7070         /* channel, so we cannot store the state in ncci_state! The */
7071         /* information which channel we received a N_DISC is thus   */
7072         /* stored in the inc_dis_ncci_table buffer.                 */
7073     for(i=0; plci->inc_dis_ncci_table[i]; i++);
7074     plci->inc_dis_ncci_table[i] = (byte) ncci;
7075
7076       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7077     if (!plci->channels
7078      && (plci->B1_resource == 16)
7079      && (plci->State <= CONNECTED))
7080     {
7081       len = 9;
7082       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7083       PUT_WORD (&plci->ncpi_buffer[1], i);
7084       PUT_WORD (&plci->ncpi_buffer[3], 0);
7085       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7086       PUT_WORD (&plci->ncpi_buffer[5], i);
7087       PUT_WORD (&plci->ncpi_buffer[7], 0);
7088       plci->ncpi_buffer[len] = 0;
7089       plci->ncpi_buffer[0] = len;
7090       if(plci->B3_prot == 4)
7091         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7092       else
7093       {
7094
7095         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7096           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7097         {
7098           plci->ncpi_buffer[++len] = 0;
7099           plci->ncpi_buffer[++len] = 0;
7100           plci->ncpi_buffer[++len] = 0;
7101           plci->ncpi_buffer[0] = len;
7102         }
7103
7104         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7105       }
7106       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7107       plci->ncpi_state = 0;
7108       sig_req(plci,HANGUP,0);
7109       send_req(plci);
7110       plci->State = OUTG_DIS_PENDING;
7111       /* disc here */
7112     }
7113     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7114      && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7115      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7116     {
7117       if (ncci_state == IDLE)
7118       {
7119         if (plci->channels)
7120           plci->channels--;
7121         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7122           if(plci->State == SUSPENDING){
7123             sendf(plci->appl,
7124                   _FACILITY_I,
7125                   Id & 0xffffL,
7126                   0,
7127                   "ws", (word)3, "\x03\x04\x00\x00");
7128             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7129           }
7130           plci_remove(plci);
7131           plci->State=IDLE;
7132         }
7133       }
7134     }
7135     else if (plci->channels)
7136     {
7137       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7138       plci->ncpi_state = 0;
7139       if ((ncci_state == OUTG_REJ_PENDING)
7140        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7141       {
7142         sig_req(plci,HANGUP,0);
7143         send_req(plci);
7144         plci->State = OUTG_DIS_PENDING;
7145       }
7146     }
7147     break;
7148   case N_RESET:
7149     a->ncci_state[ncci] = INC_RES_PENDING;
7150     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7151     break;
7152   case N_RESET_ACK:
7153     a->ncci_state[ncci] = CONNECTED;
7154     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7155     break;
7156
7157   case N_UDATA:
7158     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7159     {
7160       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7161       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7162       plci->NL.R = plci->RData;
7163       plci->NL.RNum = 1;
7164       return;
7165     }
7166   case N_BDATA:
7167   case N_DATA:
7168     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7169      || (a->ncci_state[ncci] == IDLE)
7170      || (a->ncci_state[ncci] == INC_DIS_PENDING))
7171     {
7172       plci->NL.RNR = 2;
7173       break;
7174     }
7175     if ((a->ncci_state[ncci] != CONNECTED)
7176      && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7177      && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7178     {
7179       dbug(1,dprintf("flow control"));
7180       plci->NL.RNR = 1; /* flow control  */
7181       channel_x_off (plci, ch, 0);
7182       break;
7183     }
7184
7185     NCCIcode = ncci | (((word)a->Id) << 8);
7186
7187                 /* count all buffers within the Application pool    */
7188                 /* belonging to the same NCCI. If this is below the */
7189                 /* number of buffers available per NCCI we accept   */
7190                 /* this packet, otherwise we reject it              */
7191     count = 0;
7192     Num = 0xffff;
7193     for(i=0; i<APPLptr->MaxBuffer; i++) {
7194       if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7195       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7196     }
7197
7198     if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7199     {
7200       dbug(3,dprintf("Flow-Control"));
7201       plci->NL.RNR = 1;
7202       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7203        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7204       {
7205         plci->NL.RNR = 2;
7206         dbug(3,dprintf("DiscardData"));
7207       } else {
7208         channel_x_off (plci, ch, 0);
7209       }
7210       break;
7211     }
7212     else
7213     {
7214       APPLptr->NCCIDataFlowCtrlTimer = 0;
7215     }
7216
7217     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7218     if(!plci->RData[0].P) {
7219       plci->NL.RNR = 1;
7220       channel_x_off (plci, ch, 0);
7221       break;
7222     }
7223
7224     APPLptr->DataNCCI[Num] = NCCIcode;
7225     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7226     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7227
7228     plci->RNum = Num;
7229     plci->RFlags = plci->NL.Ind>>4;
7230     plci->RData[0].PLength = APPLptr->MaxDataLength;
7231     plci->NL.R = plci->RData;
7232     if ((plci->NL.RLength != 0)
7233      && ((plci->B2_prot == B2_V120_ASYNC)
7234       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7235       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7236     {
7237       plci->RData[1].P = plci->RData[0].P;
7238       plci->RData[1].PLength = plci->RData[0].PLength;
7239       plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7240       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7241         plci->RData[0].PLength = 1;
7242       else
7243         plci->RData[0].PLength = 2;
7244       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7245         plci->RFlags |= 0x0010;
7246       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7247         plci->RFlags |= 0x8000;
7248       plci->NL.RNum = 2;
7249     }
7250     else
7251     {
7252       if((plci->NL.Ind &0x0f)==N_UDATA)
7253         plci->RFlags |= 0x0010;
7254
7255       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7256         plci->RFlags |= 0x0001;
7257
7258       plci->NL.RNum = 1;
7259     }
7260     break;
7261   case N_DATA_ACK:
7262     data_ack (plci, ch);
7263     break;
7264   default:
7265     plci->NL.RNR = 2;
7266     break;
7267   }
7268 }
7269
7270 /*------------------------------------------------------------------*/
7271 /* find a free PLCI                                                 */
7272 /*------------------------------------------------------------------*/
7273
7274 static word get_plci(DIVA_CAPI_ADAPTER *a)
7275 {
7276   word i,j;
7277   PLCI   * plci;
7278
7279   dump_plcis (a);
7280   for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7281   if(i==a->max_plci) {
7282     dbug(1,dprintf("get_plci: out of PLCIs"));
7283     return 0;
7284   }
7285   plci = &a->plci[i];
7286   plci->Id = (byte)(i+1);
7287
7288   plci->Sig.Id = 0;
7289   plci->NL.Id = 0;
7290   plci->sig_req = 0;
7291   plci->nl_req = 0;
7292
7293   plci->appl = NULL;
7294   plci->relatedPTYPLCI = NULL;
7295   plci->State = IDLE;
7296   plci->SuppState = IDLE;
7297   plci->channels = 0;
7298   plci->tel = 0;
7299   plci->B1_resource = 0;
7300   plci->B2_prot = 0;
7301   plci->B3_prot = 0;
7302
7303   plci->command = 0;
7304   plci->m_command = 0;
7305   init_internal_command_queue (plci);
7306   plci->number = 0;
7307   plci->req_in_start = 0;
7308   plci->req_in = 0;
7309   plci->req_out = 0;
7310   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7311   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7312   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7313
7314   plci->data_sent = false;
7315   plci->send_disc = 0;
7316   plci->sig_global_req = 0;
7317   plci->sig_remove_id = 0;
7318   plci->nl_global_req = 0;
7319   plci->nl_remove_id = 0;
7320   plci->adv_nl = 0;
7321   plci->manufacturer = false;
7322   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7323   plci->spoofed_msg = 0;
7324   plci->ptyState = 0;
7325   plci->cr_enquiry = false;
7326   plci->hangup_flow_ctrl_timer = 0;
7327
7328   plci->ncci_ring_list = 0;
7329   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7330   clear_c_ind_mask (plci);
7331   set_group_ind_mask (plci);
7332   plci->fax_connect_info_length = 0;
7333   plci->nsf_control_bits = 0;
7334   plci->ncpi_state = 0x00;
7335   plci->ncpi_buffer[0] = 0;
7336
7337   plci->requested_options_conn = 0;
7338   plci->requested_options = 0;
7339   plci->notifiedcall = 0;
7340   plci->vswitchstate = 0;
7341   plci->vsprot = 0;
7342   plci->vsprotdialect = 0;
7343   init_b1_config (plci);
7344   dbug(1,dprintf("get_plci(%x)",plci->Id));
7345   return i+1;
7346 }
7347
7348 /*------------------------------------------------------------------*/
7349 /* put a parameter in the parameter buffer                          */
7350 /*------------------------------------------------------------------*/
7351
7352 static void add_p(PLCI   * plci, byte code, byte   * p)
7353 {
7354   word p_length;
7355
7356   p_length = 0;
7357   if(p) p_length = p[0];
7358   add_ie(plci, code, p, p_length);
7359 }
7360
7361 /*------------------------------------------------------------------*/
7362 /* put a structure in the parameter buffer                          */
7363 /*------------------------------------------------------------------*/
7364 static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7365 {
7366   if(p) add_ie(plci, code, p->info, (word)p->length);
7367 }
7368
7369 /*------------------------------------------------------------------*/
7370 /* put multiple structures in the parameter buffer                  */
7371 /*------------------------------------------------------------------*/
7372 static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7373 {
7374   byte i;
7375
7376   if(p){
7377     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7378     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7379       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7380       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7381     }
7382   }
7383 }
7384
7385 /*------------------------------------------------------------------*/
7386 /* return the channel number sent by the application in a esc_chi   */
7387 /*------------------------------------------------------------------*/
7388 static byte getChannel(API_PARSE * p)
7389 {
7390   byte i;
7391
7392   if(p){
7393     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7394       if(p->info[i]==2){
7395         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7396       }
7397     }
7398   }
7399   return 0;
7400 }
7401
7402
7403 /*------------------------------------------------------------------*/
7404 /* put an information element in the parameter buffer               */
7405 /*------------------------------------------------------------------*/
7406
7407 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7408 {
7409   word i;
7410
7411   if(!(code &0x80) && !p_length) return;
7412
7413   if(plci->req_in==plci->req_in_start) {
7414     plci->req_in +=2;
7415   }
7416   else {
7417     plci->req_in--;
7418   }
7419   plci->RBuffer[plci->req_in++] = code;
7420
7421   if(p) {
7422     plci->RBuffer[plci->req_in++] = (byte)p_length;
7423     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7424   }
7425
7426   plci->RBuffer[plci->req_in++] = 0;
7427 }
7428
7429 /*------------------------------------------------------------------*/
7430 /* put a unstructured data into the buffer                          */
7431 /*------------------------------------------------------------------*/
7432
7433 static void add_d(PLCI *plci, word length, byte *p)
7434 {
7435   word i;
7436
7437   if(plci->req_in==plci->req_in_start) {
7438     plci->req_in +=2;
7439   }
7440   else {
7441     plci->req_in--;
7442   }
7443   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7444 }
7445
7446 /*------------------------------------------------------------------*/
7447 /* put parameters from the Additional Info parameter in the         */
7448 /* parameter buffer                                                 */
7449 /*------------------------------------------------------------------*/
7450
7451 static void add_ai(PLCI *plci, API_PARSE *ai)
7452 {
7453   word i;
7454     API_PARSE ai_parms[5];
7455
7456   for(i=0;i<5;i++) ai_parms[i].length = 0;
7457
7458   if(!ai->length)
7459     return;
7460   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7461     return;
7462
7463   add_s (plci,KEY,&ai_parms[1]);
7464   add_s (plci,UUI,&ai_parms[2]);
7465   add_ss(plci,FTY,&ai_parms[3]);
7466 }
7467
7468 /*------------------------------------------------------------------*/
7469 /* put parameter for b1 protocol in the parameter buffer            */
7470 /*------------------------------------------------------------------*/
7471
7472 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7473                    word b1_facilities)
7474 {
7475     API_PARSE bp_parms[8];
7476     API_PARSE mdm_cfg[9];
7477     API_PARSE global_config[2];
7478     byte cai[256];
7479   byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7480   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7481   word i;
7482
7483     API_PARSE mdm_cfg_v18[4];
7484   word j, n, w;
7485   dword d;
7486
7487
7488   for(i=0;i<8;i++) bp_parms[i].length = 0;
7489   for(i=0;i<2;i++) global_config[i].length = 0;
7490
7491   dbug(1,dprintf("add_b1"));
7492   api_save_msg(bp, "s", &plci->B_protocol);
7493
7494   if(b_channel_info==2){
7495     plci->B1_resource = 0;
7496     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7497     add_p(plci, CAI, "\x01\x00");
7498     dbug(1,dprintf("Cai=1,0 (no resource)"));
7499     return 0;
7500   }
7501
7502   if(plci->tel == CODEC_PERMANENT) return 0;
7503   else if(plci->tel == CODEC){
7504     plci->B1_resource = 1;
7505     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7506     add_p(plci, CAI, "\x01\x01");
7507     dbug(1,dprintf("Cai=1,1 (Codec)"));
7508     return 0;
7509   }
7510   else if(plci->tel == ADV_VOICE){
7511     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7512     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7513     voice_cai[1] = plci->B1_resource;
7514     PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7515     add_p(plci, CAI, voice_cai);
7516     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7517     return 0;
7518   }
7519   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7520   if (plci->call_dir & CALL_DIR_OUT)
7521     plci->call_dir |= CALL_DIR_ORIGINATE;
7522   else if (plci->call_dir & CALL_DIR_IN)
7523     plci->call_dir |= CALL_DIR_ANSWER;
7524
7525   if(!bp->length){
7526     plci->B1_resource = 0x5;
7527     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7528     add_p(plci, CAI, "\x01\x05");
7529     return 0;
7530   }
7531
7532   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7533   if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7534   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7535   {
7536     bp_parms[6].length = 0;
7537     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7538     {
7539       dbug(1,dprintf("b-form.!"));
7540       return _WRONG_MESSAGE_FORMAT;
7541     }
7542   }
7543   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7544   {
7545     dbug(1,dprintf("b-form.!"));
7546     return _WRONG_MESSAGE_FORMAT;
7547   }
7548
7549   if(bp_parms[6].length)
7550   {
7551     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7552     {
7553       return _WRONG_MESSAGE_FORMAT;
7554     }
7555     switch(GET_WORD(global_config[0].info))
7556     {
7557     case 1:
7558       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7559       break;
7560     case 2:
7561       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7562       break;
7563     }
7564   }
7565   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7566
7567
7568   if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7569    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7570   {
7571     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7572     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7573     cai[1] = plci->B1_resource;
7574     cai[2] = 0;
7575     cai[3] = 0;
7576     cai[4] = 0;
7577     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7578     for (i = 0; i < bp_parms[3].length; i++)
7579       cai[7+i] = bp_parms[3].info[1+i];
7580     cai[0] = 6 + bp_parms[3].length;
7581     add_p(plci, CAI, cai);
7582     return 0;
7583   }
7584
7585
7586   if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7587    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7588   {
7589     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7590     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7591     cai[1] = plci->B1_resource;
7592     cai[2] = 0;
7593     cai[3] = 0;
7594     cai[4] = 0;
7595     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7596     cai[0] = 6;
7597     add_p(plci, CAI, cai);
7598     return 0;
7599   }
7600
7601
7602   if ((GET_WORD(bp_parms[0].info) >= 32)
7603    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7604     && ((GET_WORD(bp_parms[0].info) != 3)
7605      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7606      || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7607   {
7608     return _B1_NOT_SUPPORTED;
7609   }
7610   plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7611     (word)(b1_facilities & ~B1_FACILITY_VOICE));
7612   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7613   cai[0] = 6;
7614   cai[1] = plci->B1_resource;
7615   for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7616
7617   if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7618    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7619    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7620   { /* B1 - modem */
7621     for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7622
7623     if (bp_parms[3].length)
7624     {
7625       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7626       {
7627         return (_WRONG_MESSAGE_FORMAT);
7628       }
7629         
7630       cai[2] = 0; /* Bit rate for adaptation */
7631
7632       dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7633
7634       PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
7635       PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7636       PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
7637       PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7638
7639       cai[3] = 0; /* Async framing parameters */
7640       switch (GET_WORD (mdm_cfg[2].info))
7641       {       /* Parity     */
7642       case 1: /* odd parity */
7643         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7644         dbug(1,dprintf("MDM: odd parity"));
7645         break;
7646
7647       case 2: /* even parity */
7648         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7649         dbug(1,dprintf("MDM: even parity"));
7650         break;
7651
7652       default:
7653         dbug(1,dprintf("MDM: no parity"));
7654         break;
7655       }
7656
7657       switch (GET_WORD (mdm_cfg[3].info))
7658       {       /* stop bits   */
7659       case 1: /* 2 stop bits */
7660         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7661         dbug(1,dprintf("MDM: 2 stop bits"));
7662         break;
7663
7664       default:
7665         dbug(1,dprintf("MDM: 1 stop bit"));
7666         break;
7667       }
7668
7669       switch (GET_WORD (mdm_cfg[1].info))
7670       {     /* char length */
7671       case 5:
7672         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7673         dbug(1,dprintf("MDM: 5 bits"));
7674         break;
7675
7676       case 6:
7677         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7678         dbug(1,dprintf("MDM: 6 bits"));
7679         break;
7680
7681       case 7:
7682         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7683         dbug(1,dprintf("MDM: 7 bits"));
7684         break;
7685
7686       default:
7687         dbug(1,dprintf("MDM: 8 bits"));
7688         break;
7689       }
7690
7691       cai[7] = 0; /* Line taking options */
7692       cai[8] = 0; /* Modulation negotiation options */
7693       cai[9] = 0; /* Modulation options */
7694
7695       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7696       {
7697         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7698         dbug(1, dprintf("MDM: Reverse direction"));
7699       }
7700
7701       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7702       {
7703         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7704         dbug(1, dprintf("MDM: Disable retrain"));
7705       }
7706
7707       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7708       {
7709         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7710         dbug(1, dprintf("MDM: Disable ring tone"));
7711       }
7712
7713       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7714       {
7715         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7716         dbug(1, dprintf("MDM: 1800 guard tone"));
7717       }
7718       else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7719       {
7720         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7721         dbug(1, dprintf("MDM: 550 guard tone"));
7722       }
7723
7724       if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7725       {
7726         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7727         dbug(1, dprintf("MDM: V100"));
7728       }
7729       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7730       {
7731         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7732         dbug(1, dprintf("MDM: IN CLASS"));
7733       }
7734       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7735       {
7736         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7737         dbug(1, dprintf("MDM: DISABLED"));
7738       }
7739       cai[0] = 20;
7740
7741       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7742        && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7743       {
7744         plci->requested_options |= 1L << PRIVATE_V18;
7745       }
7746       if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7747         plci->requested_options |= 1L << PRIVATE_VOWN;
7748
7749       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7750         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7751       {
7752         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7753         {
7754           i = 27;
7755           if (mdm_cfg[6].length >= 4)
7756           {
7757             d = GET_DWORD(&mdm_cfg[6].info[1]);
7758             cai[7] |= (byte) d;          /* line taking options */
7759             cai[9] |= (byte)(d >> 8);    /* modulation options */
7760             cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7761             cai[++i] = (byte)(d >> 24);
7762             if (mdm_cfg[6].length >= 8)
7763             {
7764               d = GET_DWORD(&mdm_cfg[6].info[5]);
7765               cai[10] |= (byte) d;        /* disabled modulations mask */
7766               cai[11] |= (byte)(d >> 8);
7767               if (mdm_cfg[6].length >= 12)
7768               {
7769                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7770                 cai[12] = (byte) d;          /* enabled modulations mask */
7771                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7772                 cai[++i] = (byte)(d >> 16);
7773                 cai[++i] = (byte)(d >> 24);
7774                 cai[++i] = 0;
7775                 if (mdm_cfg[6].length >= 14)
7776                 {
7777                   w = GET_WORD(&mdm_cfg[6].info[13]);
7778                   if (w != 0)
7779                     PUT_WORD(&cai[13], w);  /* min tx speed */
7780                   if (mdm_cfg[6].length >= 16)
7781                   {
7782                     w = GET_WORD(&mdm_cfg[6].info[15]);
7783                     if (w != 0)
7784                       PUT_WORD(&cai[15], w);  /* max tx speed */
7785                     if (mdm_cfg[6].length >= 18)
7786                     {
7787                       w = GET_WORD(&mdm_cfg[6].info[17]);
7788                       if (w != 0)
7789                         PUT_WORD(&cai[17], w);  /* min rx speed */
7790                       if (mdm_cfg[6].length >= 20)
7791                       {
7792                         w = GET_WORD(&mdm_cfg[6].info[19]);
7793                         if (w != 0)
7794                           PUT_WORD(&cai[19], w);  /* max rx speed */
7795                         if (mdm_cfg[6].length >= 22)
7796                         {
7797                           w = GET_WORD(&mdm_cfg[6].info[21]);
7798                           cai[23] = (byte)(-((short) w));  /* transmit level */
7799                           if (mdm_cfg[6].length >= 24)
7800                           {
7801                             w = GET_WORD(&mdm_cfg[6].info[23]);
7802                             cai[22] |= (byte) w;        /* info options mask */
7803                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7804                           }
7805                         }
7806                       }
7807                     }
7808                   }
7809                 }
7810               }
7811             }
7812           }
7813           cai[27] = i - 27;
7814           i++;
7815           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7816           {
7817             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7818             {
7819               for (n = 0; n < 3; n++)
7820               {
7821                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7822                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7823                   cai[i+j] = mdm_cfg_v18[n].info[j];
7824                 i += cai[i] + 1;
7825               }
7826             }
7827           }
7828           cai[0] = (byte)(i - 1);
7829         }
7830       }
7831
7832     }
7833   }
7834   if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
7835      GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
7836   {
7837     if(bp_parms[3].length){
7838       dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7839       switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
7840         case 0:
7841         case 56000:
7842           if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
7843             dbug(1,dprintf("56k sync HSCX"));
7844             cai[1] = 8;
7845             cai[2] = 0;
7846             cai[3] = 0;
7847           }
7848           else if(GET_WORD(bp_parms[0].info)==2){
7849             dbug(1,dprintf("56k async DSP"));
7850             cai[2] = 9;
7851           }
7852           break;
7853         case 50:     cai[2] = 1;  break;
7854         case 75:     cai[2] = 1;  break;
7855         case 110:    cai[2] = 1;  break;
7856         case 150:    cai[2] = 1;  break;
7857         case 200:    cai[2] = 1;  break;
7858         case 300:    cai[2] = 1;  break;
7859         case 600:    cai[2] = 1;  break;
7860         case 1200:   cai[2] = 2;  break;
7861         case 2400:   cai[2] = 3;  break;
7862         case 4800:   cai[2] = 4;  break;
7863         case 7200:   cai[2] = 10; break;
7864         case 9600:   cai[2] = 5;  break;
7865         case 12000:  cai[2] = 13; break;
7866         case 24000:  cai[2] = 0;  break;
7867         case 14400:  cai[2] = 11; break;
7868         case 19200:  cai[2] = 6;  break;
7869         case 28800:  cai[2] = 12; break;
7870         case 38400:  cai[2] = 7;  break;
7871         case 48000:  cai[2] = 8;  break;
7872         case 76:     cai[2] = 15; break;  /* 75/1200     */
7873         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7874         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7875
7876         default:
7877           return _B1_PARM_NOT_SUPPORTED;
7878       }
7879       cai[3] = 0;
7880       if (cai[1] == 13)                                        /* v.110 async */
7881       {
7882         if (bp_parms[3].length >= 8)
7883         {
7884           switch (GET_WORD (&bp_parms[3].info[3]))
7885           {       /* char length */
7886           case 5:
7887             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7888             break;
7889           case 6:
7890             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7891             break;
7892           case 7:
7893             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7894             break;
7895           }
7896           switch (GET_WORD (&bp_parms[3].info[5]))
7897           {       /* Parity     */
7898           case 1: /* odd parity */
7899             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7900             break;
7901           case 2: /* even parity */
7902             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7903             break;
7904           }
7905           switch (GET_WORD (&bp_parms[3].info[7]))
7906           {       /* stop bits   */
7907           case 1: /* 2 stop bits */
7908             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7909             break;
7910           }
7911         }
7912       }
7913     }
7914     else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7915       dbug(1,dprintf("V.110 default 56k sync"));
7916       cai[1] = 8;
7917       cai[2] = 0;
7918       cai[3] = 0;
7919     }
7920     else {
7921       dbug(1,dprintf("V.110 default 9600 async"));
7922       cai[2] = 5;
7923     }
7924   }
7925   PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7926   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]));
7927 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7928
7929   add_p(plci, CAI, cai);
7930   return 0;
7931 }
7932
7933 /*------------------------------------------------------------------*/
7934 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7935 /*------------------------------------------------------------------*/
7936
7937 static word add_b23(PLCI *plci, API_PARSE *bp)
7938 {
7939   word i, fax_control_bits;
7940   byte pos, len;
7941   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7942     API_PARSE bp_parms[8];
7943   API_PARSE * b1_config;
7944   API_PARSE * b2_config;
7945     API_PARSE b2_config_parms[8];
7946   API_PARSE * b3_config;
7947     API_PARSE b3_config_parms[6];
7948     API_PARSE global_config[2];
7949
7950   static byte llc[3] = {2,0,0};
7951   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7952   static byte nlc[256];
7953   static byte lli[12] = {1,1};
7954
7955   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7956   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7957
7958   const byte llc3[] = {4,3,2,2,6,6,0};
7959   const byte header[] = {0,2,3,3,0,0,0};
7960
7961   for(i=0;i<8;i++) bp_parms[i].length = 0;
7962   for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7963   for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7964
7965   lli[0] = 1;
7966   lli[1] = 1;
7967   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7968     lli[1] |= 2;
7969   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7970     lli[1] |= 4;
7971
7972   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7973     lli[1] |= 0x10;
7974     if (plci->rx_dma_descriptor <= 0) {
7975       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7976       if (plci->rx_dma_descriptor >= 0)
7977         plci->rx_dma_descriptor++;
7978     }
7979     if (plci->rx_dma_descriptor > 0) {
7980       lli[0] = 6;
7981       lli[1] |= 0x40;
7982       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7983       lli[3] = (byte)plci->rx_dma_magic;
7984       lli[4] = (byte)(plci->rx_dma_magic >>  8);
7985       lli[5] = (byte)(plci->rx_dma_magic >> 16);
7986       lli[6] = (byte)(plci->rx_dma_magic >> 24);
7987     }
7988   }
7989
7990   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7991     lli[1] |= 0x20;
7992   }
7993
7994   dbug(1,dprintf("add_b23"));
7995   api_save_msg(bp, "s", &plci->B_protocol);
7996
7997   if(!bp->length && plci->tel)
7998   {
7999     plci->adv_nl = true;
8000     dbug(1,dprintf("Default adv.Nl"));
8001     add_p(plci,LLI,lli);
8002     plci->B2_prot = 1 /*XPARENT*/;
8003     plci->B3_prot = 0 /*XPARENT*/;
8004     llc[1] = 2;
8005     llc[2] = 4;
8006     add_p(plci, LLC, llc);
8007     dlc[0] = 2;
8008     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8009     add_p(plci, DLC, dlc);
8010     return 0;
8011   }
8012
8013   if(!bp->length) /*default*/
8014   {   
8015     dbug(1,dprintf("ret default"));
8016     add_p(plci,LLI,lli);
8017     plci->B2_prot = 0 /*X.75   */;
8018     plci->B3_prot = 0 /*XPARENT*/;
8019     llc[1] = 1;
8020     llc[2] = 4;
8021     add_p(plci, LLC, llc);
8022     dlc[0] = 2;
8023     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8024     add_p(plci, DLC, dlc);
8025     return 0;
8026   }
8027   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8028   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8029
8030   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8031   {
8032     bp_parms[6].length = 0;
8033     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8034     {
8035       dbug(1,dprintf("b-form.!"));
8036       return _WRONG_MESSAGE_FORMAT;
8037     }
8038   }
8039   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8040   {
8041     dbug(1,dprintf("b-form.!"));
8042     return _WRONG_MESSAGE_FORMAT;
8043   }
8044
8045   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8046   {  
8047     if(GET_WORD(bp_parms[1].info)!=1
8048     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8049     plci->adv_nl = true;
8050   }
8051   else if(plci->tel) return _B2_NOT_SUPPORTED;
8052
8053
8054   if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8055    && (GET_WORD(bp_parms[2].info) == B3_RTP)
8056    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8057   {
8058     add_p(plci,LLI,lli);
8059     plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8060     plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8061     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8062     llc[2] = 4;
8063     add_p(plci, LLC, llc);
8064     dlc[0] = 2;
8065     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8066     dlc[3] = 3; /* Addr A */
8067     dlc[4] = 1; /* Addr B */
8068     dlc[5] = 7; /* modulo mode */
8069     dlc[6] = 7; /* window size */
8070     dlc[7] = 0; /* XID len Lo  */
8071     dlc[8] = 0; /* XID len Hi  */
8072     for (i = 0; i < bp_parms[4].length; i++)
8073       dlc[9+i] = bp_parms[4].info[1+i];
8074     dlc[0] = (byte)(8 + bp_parms[4].length);
8075     add_p(plci, DLC, dlc);
8076     for (i = 0; i < bp_parms[5].length; i++)
8077       nlc[1+i] = bp_parms[5].info[1+i];
8078     nlc[0] = (byte)(bp_parms[5].length);
8079     add_p(plci, NLC, nlc);
8080     return 0;
8081   }
8082
8083
8084
8085   if ((GET_WORD(bp_parms[1].info) >= 32)
8086    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8087     && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8088      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8089
8090   {
8091     return _B2_NOT_SUPPORTED;
8092   }
8093   if ((GET_WORD(bp_parms[2].info) >= 32)
8094    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8095   {
8096     return _B3_NOT_SUPPORTED;
8097   }
8098   if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8099    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8100     || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8101     || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8102   {
8103     return (add_modem_b23 (plci, bp_parms));
8104   }
8105
8106   add_p(plci,LLI,lli);
8107
8108   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8109   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8110   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8111
8112   if(bp_parms[6].length)
8113   {
8114     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8115     {
8116       return _WRONG_MESSAGE_FORMAT;
8117     }
8118     switch(GET_WORD(global_config[0].info))
8119     {
8120     case 1:
8121       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8122       break;
8123     case 2:
8124       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8125       break;
8126     }
8127   }
8128   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8129
8130
8131   if (plci->B2_prot == B2_PIAFS)
8132     llc[1] = PIAFS_CRC;
8133   else
8134 /* IMPLEMENT_PIAFS */
8135   {
8136     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8137              llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8138   }
8139   llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8140
8141   add_p(plci, LLC, llc);
8142
8143   dlc[0] = 2;
8144   PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8145                       header[GET_WORD(bp_parms[2].info)]);
8146
8147   b1_config = &bp_parms[3];
8148   nlc[0] = 0;
8149   if(plci->B3_prot == 4
8150   || plci->B3_prot == 5)
8151   {
8152     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8153     nlc[0] = sizeof(T30_INFO);
8154     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8155       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8156     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8157     if(b1_config->length>=2)
8158     {
8159       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8160     }
8161   }
8162   b2_config = &bp_parms[4];
8163
8164
8165   if (llc[1] == PIAFS_CRC)
8166   {
8167     if (plci->B3_prot != B3_TRANSPARENT)
8168     {
8169       return _B_STACK_NOT_SUPPORTED;
8170     }
8171     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8172       return _WRONG_MESSAGE_FORMAT;
8173     }
8174     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8175     dlc[3] = 0; /* Addr A */
8176     dlc[4] = 0; /* Addr B */
8177     dlc[5] = 0; /* modulo mode */
8178     dlc[6] = 0; /* window size */
8179     if (b2_config->length >= 7){
8180       dlc[ 7] = 7; 
8181       dlc[ 8] = 0; 
8182       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8183       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8184       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8185       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8186       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8187       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8188       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8189       dlc[ 0] = 15;
8190       if(b2_config->length >= 8) { /* PIAFS control abilities */
8191         dlc[ 7] = 10; 
8192         dlc[16] = 2; /* Length of PIAFS extension */
8193         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8194         dlc[18] = b2_config_parms[4].info[0]; /* value */
8195         dlc[ 0] = 18;
8196       }
8197     }
8198     else /* default values, 64K, variable, no compression */
8199     {
8200       dlc[ 7] = 7; 
8201       dlc[ 8] = 0; 
8202       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8203       dlc[10] = 0x03; /* V.42bis P0 */
8204       dlc[11] = 0;    /* V.42bis P0 */
8205       dlc[12] = 0;    /* V.42bis P1 */
8206       dlc[13] = 0;    /* V.42bis P1 */
8207       dlc[14] = 0;    /* V.42bis P2 */
8208       dlc[15] = 0;    /* V.42bis P2 */
8209     dlc[ 0] = 15;
8210     }
8211     add_p(plci, DLC, dlc);
8212   }
8213   else
8214
8215   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8216   {
8217     if (plci->B3_prot != B3_TRANSPARENT)
8218       return _B_STACK_NOT_SUPPORTED;
8219
8220     dlc[0] = 6;
8221     PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8222     dlc[3] = 0x08;
8223     dlc[4] = 0x01;
8224     dlc[5] = 127;
8225     dlc[6] = 7;
8226     if (b2_config->length != 0)
8227     {
8228       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8229         return _WRONG_MESSAGE_FORMAT;
8230       }
8231       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8232       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8233       if (b2_config->info[3] != 128)
8234       {
8235         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8236         return _B2_PARM_NOT_SUPPORTED;
8237       }
8238       dlc[5] = (byte)(b2_config->info[3] - 1);
8239       dlc[6] = b2_config->info[4];
8240       if(llc[1]==V120_V42BIS){
8241         if (b2_config->length >= 10){
8242           dlc[ 7] = 6; 
8243           dlc[ 8] = 0; 
8244           dlc[ 9] = b2_config_parms[4].info[0];
8245           dlc[10] = b2_config_parms[4].info[1];
8246           dlc[11] = b2_config_parms[5].info[0];
8247           dlc[12] = b2_config_parms[5].info[1];
8248           dlc[13] = b2_config_parms[6].info[0];
8249           dlc[14] = b2_config_parms[6].info[1];
8250           dlc[ 0] = 14;
8251           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8252           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8253           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8254         }
8255         else {
8256           dlc[ 6] = 14;
8257         }
8258       }
8259     }
8260   }
8261   else
8262   {
8263     if(b2_config->length)
8264     {
8265       dbug(1,dprintf("B2-Config"));
8266       if(llc[1]==X75_V42BIS){
8267         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8268         {
8269           return _WRONG_MESSAGE_FORMAT;
8270         }
8271       }
8272       else {
8273         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8274         {
8275           return _WRONG_MESSAGE_FORMAT;
8276         }
8277       }
8278           /* if B2 Protocol is LAPD, b2_config structure is different */
8279       if(llc[1]==6)
8280       {
8281         dlc[0] = 4;
8282         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8283         else dlc[2] = 0x01;
8284         if( (b2_config->length>=2) && (plci->B2_prot==12) )
8285         {
8286           SAPI = b2_config->info[2];    /* SAPI */
8287         }
8288         dlc[1] = SAPI;
8289         if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8290         {
8291           dlc[3] = 127;      /* Mode */
8292         }
8293         else
8294         {
8295           dlc[3] = 7;        /* Mode */
8296         }
8297    
8298         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8299         else dlc[4] = 1;
8300         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8301         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8302       }
8303       else
8304       {
8305         dlc[0] = (byte)(b2_config_parms[4].length+6);
8306         dlc[3] = b2_config->info[1];
8307         dlc[4] = b2_config->info[2];
8308         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8309           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8310           return _B2_PARM_NOT_SUPPORTED;
8311         }
8312
8313         dlc[5] = (byte)(b2_config->info[3]-1);
8314         dlc[6] = b2_config->info[4];
8315         if(dlc[6]>dlc[5]){
8316           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]));
8317           return _B2_PARM_NOT_SUPPORTED;
8318         }
8319  
8320         if(llc[1]==X75_V42BIS) {
8321           if (b2_config->length >= 10){
8322             dlc[ 7] = 6; 
8323             dlc[ 8] = 0; 
8324             dlc[ 9] = b2_config_parms[4].info[0];
8325             dlc[10] = b2_config_parms[4].info[1];
8326             dlc[11] = b2_config_parms[5].info[0];
8327             dlc[12] = b2_config_parms[5].info[1];
8328             dlc[13] = b2_config_parms[6].info[0];
8329             dlc[14] = b2_config_parms[6].info[1];
8330             dlc[ 0] = 14;
8331             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8332             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8333             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8334           }
8335           else {
8336             dlc[ 6] = 14;
8337           }
8338
8339         }
8340         else {
8341           PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8342           for(i=0; i<b2_config_parms[4].length; i++)
8343             dlc[11+i] = b2_config_parms[4].info[1+i];
8344         }
8345       }
8346     }
8347   }
8348   add_p(plci, DLC, dlc);
8349
8350   b3_config = &bp_parms[5];
8351   if(b3_config->length)
8352   {
8353     if(plci->B3_prot == 4 
8354     || plci->B3_prot == 5)
8355     {
8356       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8357       {
8358         return _WRONG_MESSAGE_FORMAT;
8359       }
8360       i = GET_WORD((byte   *)(b3_config_parms[0].info));
8361       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8362         ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8363       ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
8364       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8365       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8366         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8367       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8368       {
8369
8370         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8371           & (1L << PRIVATE_FAX_PAPER_FORMATS))
8372         {
8373           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8374             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8375             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8376         }
8377
8378  ((T30_INFO *)&nlc[1])->recording_properties =
8379    T30_RECORDING_WIDTH_ISO_A3 |
8380    (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8381    (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8382       }
8383       if(plci->B3_prot == 5)
8384       {
8385         if (i & 0x0002) /* Accept incoming fax-polling requests */
8386           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8387         if (i & 0x2000) /* Do not use MR compression */
8388           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8389         if (i & 0x4000) /* Do not use MMR compression */
8390           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8391         if (i & 0x8000) /* Do not use ECM */
8392           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8393         if (plci->fax_connect_info_length != 0)
8394         {
8395           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8396           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8397           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8398           fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8399             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8400         }
8401       }
8402       /* copy station id to NLC */
8403       for(i=0; i < T30_MAX_STATION_ID_LENGTH; i++)
8404       {
8405         if(i<b3_config_parms[2].length)
8406         {
8407           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8408         }
8409         else
8410         {
8411           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8412         }
8413       }
8414       ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8415       /* copy head line to NLC */
8416       if(b3_config_parms[3].length)
8417       {
8418
8419         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8420         if (pos != 0)
8421         {
8422           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8423             pos = 0;
8424           else
8425           {
8426             nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8427             nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8428             len = (byte)b3_config_parms[2].length;
8429             if (len > 20)
8430               len = 20;
8431             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8432             {
8433               for (i = 0; i < len; i++)
8434                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8435               nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8436               nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8437             }
8438           }
8439         }
8440
8441         len = (byte)b3_config_parms[3].length;
8442         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8443           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8444         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8445         nlc[0] += (byte)(pos + len);
8446         for (i = 0; i < len; i++)
8447           nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte   *)b3_config_parms[3].info)[1+i];
8448       } else
8449         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8450
8451       plci->nsf_control_bits = 0;
8452       if(plci->B3_prot == 5)
8453       {
8454         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8455          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8456         {
8457           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8458         }
8459         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8460          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8461         {
8462           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8463         }
8464         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8465           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8466         {
8467         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8469         {
8470           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8471           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8472             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8473           }
8474             len = nlc[0];
8475           pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8476    if (pos < plci->fax_connect_info_length)
8477    {
8478      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8479               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8480           }
8481    else
8482      nlc[++len] = 0;
8483    if (pos < plci->fax_connect_info_length)
8484    {
8485      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8486               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8487           }
8488    else
8489      nlc[++len] = 0;
8490           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8491             & (1L << PRIVATE_FAX_NONSTANDARD))
8492           {
8493      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8494      {
8495               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8496                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8497        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8498                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8499             }
8500      else
8501      {
8502               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8503               {
8504                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8505                 nlc[++len] = 0;
8506               }
8507        else
8508        {
8509                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8510                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8511          nlc[++len] = (byte)(b3_config_parms[4].length);
8512          for (i = 0; i < b3_config_parms[4].length; i++)
8513     nlc[++len] = b3_config_parms[4].info[1+i];
8514        }
8515             }
8516           }
8517             nlc[0] = len;
8518    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8519     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8520    {
8521             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8522           }
8523         }
8524       }
8525
8526       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8527       len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8528       for (i = 0; i < len; i++)
8529         plci->fax_connect_info_buffer[i] = nlc[1+i];
8530       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8531       i += ((T30_INFO *)&nlc[1])->head_line_len;
8532       while (i < nlc[0])
8533         plci->fax_connect_info_buffer[len++] = nlc[++i];
8534       plci->fax_connect_info_length = len;
8535     }
8536     else
8537     {
8538       nlc[0] = 14;
8539       if(b3_config->length!=16)
8540         return _B3_PARM_NOT_SUPPORTED;
8541       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8542       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8543         return _B3_PARM_NOT_SUPPORTED;
8544       nlc[13] = b3_config->info[13];
8545       if(GET_WORD(&b3_config->info[15])>=nlc[13])
8546         return _B3_PARM_NOT_SUPPORTED;
8547       nlc[14] = b3_config->info[15];
8548     }
8549   }
8550   else
8551   {
8552     if (plci->B3_prot == 4 
8553      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8554   }
8555   add_p(plci, NLC, nlc);
8556   return 0;
8557 }
8558
8559 /*----------------------------------------------------------------*/
8560 /*      make the same as add_b23, but only for the modem related  */
8561 /*      L2 and L3 B-Chan protocol.                                */
8562 /*                                                                */
8563 /*      Enabled L2 and L3 Configurations:                         */
8564 /*        If L1 == Modem all negotiation                          */
8565 /*          only L2 == Modem with full negotiation is allowed     */
8566 /*        If L1 == Modem async or sync                            */
8567 /*          only L2 == Transparent is allowed                     */
8568 /*        L3 == Modem or L3 == Transparent are allowed            */
8569 /*      B2 Configuration for modem:                               */
8570 /*          word : enable/disable compression, bitoptions         */
8571 /*      B3 Configuration for modem:                               */
8572 /*          empty                                                 */
8573 /*----------------------------------------------------------------*/
8574 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8575 {
8576   static byte lli[12] = {1,1};
8577   static byte llc[3] = {2,0,0};
8578   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8579     API_PARSE mdm_config[2];
8580   word i;
8581   word b2_config = 0;
8582
8583   for(i=0;i<2;i++) mdm_config[i].length = 0;
8584   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8585
8586   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8587     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8588    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8589     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8590   {
8591     return (_B_STACK_NOT_SUPPORTED);
8592   }
8593   if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8594    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8595   {
8596     return (_B_STACK_NOT_SUPPORTED);
8597   }
8598
8599   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8600   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8601
8602   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8603   {
8604     if (api_parse (&bp_parms[4].info[1],
8605                   (word)bp_parms[4].length, "w",
8606                   mdm_config))
8607     {
8608       return (_WRONG_MESSAGE_FORMAT);
8609     }
8610     b2_config = GET_WORD(mdm_config[0].info);
8611   }
8612
8613   /* OK, L2 is modem */
8614
8615   lli[0] = 1;
8616   lli[1] = 1;
8617   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8618     lli[1] |= 2;
8619   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8620     lli[1] |= 4;
8621
8622   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8623     lli[1] |= 0x10;
8624     if (plci->rx_dma_descriptor <= 0) {
8625       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8626       if (plci->rx_dma_descriptor >= 0)
8627         plci->rx_dma_descriptor++;
8628     }
8629     if (plci->rx_dma_descriptor > 0) {
8630       lli[1] |= 0x40;
8631       lli[0] = 6;
8632       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8633       lli[3] = (byte)plci->rx_dma_magic;
8634       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8635       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8636       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8637     }
8638   }
8639
8640   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8641     lli[1] |= 0x20;
8642   }
8643
8644   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8645     /*V42*/ 10 : /*V42_IN*/ 9;
8646   llc[2] = 4;                      /* pass L3 always transparent */
8647   add_p(plci, LLI, lli);
8648   add_p(plci, LLC, llc);
8649   i =  1;
8650   PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8651   i += 2;
8652   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8653   {
8654     if (bp_parms[4].length)
8655   {
8656     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8657     dlc[i++] = 3; /* Addr A */
8658     dlc[i++] = 1; /* Addr B */
8659     dlc[i++] = 7; /* modulo mode */
8660     dlc[i++] = 7; /* window size */
8661     dlc[i++] = 0; /* XID len Lo  */
8662     dlc[i++] = 0; /* XID len Hi  */
8663
8664     if (b2_config & MDM_B2_DISABLE_V42bis)
8665     {
8666       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8667     }
8668     if (b2_config & MDM_B2_DISABLE_MNP)
8669     {
8670       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8671     }
8672     if (b2_config & MDM_B2_DISABLE_TRANS)
8673     {
8674       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8675     }
8676     if (b2_config & MDM_B2_DISABLE_V42)
8677     {
8678       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8679     }
8680     if (b2_config & MDM_B2_DISABLE_COMP)
8681     {
8682       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8683     }
8684     i++;
8685   }
8686   }
8687   else
8688   {
8689     dlc[i++] = 3; /* Addr A */
8690     dlc[i++] = 1; /* Addr B */
8691     dlc[i++] = 7; /* modulo mode */
8692     dlc[i++] = 7; /* window size */
8693     dlc[i++] = 0; /* XID len Lo  */
8694     dlc[i++] = 0; /* XID len Hi  */
8695     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8696                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8697                DLC_MODEMPROT_DISABLE_V42_DETECT |
8698                DLC_MODEMPROT_DISABLE_COMPRESSION;
8699   }
8700   dlc[0] = (byte)(i - 1);
8701 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8702   add_p(plci, DLC, dlc);
8703   return (0);
8704 }
8705
8706
8707 /*------------------------------------------------------------------*/
8708 /* send a request for the signaling entity                          */
8709 /*------------------------------------------------------------------*/
8710
8711 static void sig_req(PLCI *plci, byte req, byte Id)
8712 {
8713   if(!plci) return;
8714   if(plci->adapter->adapter_disabled) return;
8715   dbug(1,dprintf("sig_req(%x)",req));
8716   if (req == REMOVE)
8717     plci->sig_remove_id = plci->Sig.Id;
8718   if(plci->req_in==plci->req_in_start) {
8719     plci->req_in +=2;
8720     plci->RBuffer[plci->req_in++] = 0;
8721   }
8722   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8723   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8724   plci->RBuffer[plci->req_in++] = req;  /* request */
8725   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8726   plci->req_in_start = plci->req_in;
8727 }
8728
8729 /*------------------------------------------------------------------*/
8730 /* send a request for the network layer entity                      */
8731 /*------------------------------------------------------------------*/
8732
8733 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8734 {
8735   if(!plci) return;
8736   if(plci->adapter->adapter_disabled) return;
8737   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8738   if (req == REMOVE)
8739   {
8740     plci->nl_remove_id = plci->NL.Id;
8741     ncci_remove (plci, 0, (byte)(ncci != 0));
8742     ncci = 0;
8743   }
8744   if(plci->req_in==plci->req_in_start) {
8745     plci->req_in +=2;
8746     plci->RBuffer[plci->req_in++] = 0;
8747   }
8748   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8749   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8750   plci->RBuffer[plci->req_in++] = req;  /* request */
8751   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8752   plci->req_in_start = plci->req_in;
8753 }
8754
8755 static void send_req(PLCI *plci)
8756 {
8757   ENTITY   * e;
8758   word l;
8759 /*  word i; */
8760
8761   if(!plci) return;
8762   if(plci->adapter->adapter_disabled) return;
8763   channel_xmit_xon (plci);
8764
8765         /* if nothing to do, return */
8766   if(plci->req_in==plci->req_out) return;
8767   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8768
8769   if(plci->nl_req || plci->sig_req) return;
8770
8771   l = GET_WORD(&plci->RBuffer[plci->req_out]);
8772   plci->req_out += 2;
8773   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8774   plci->req_out += l;
8775   if(plci->RBuffer[plci->req_out]==1)
8776   {
8777     e = &plci->NL;
8778     plci->req_out++;
8779     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8780     e->ReqCh = plci->RBuffer[plci->req_out++];
8781     if(!(e->Id & 0x1f))
8782     {
8783       e->Id = NL_ID;
8784       plci->RBuffer[plci->req_out-4] = CAI;
8785       plci->RBuffer[plci->req_out-3] = 1;
8786       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8787       plci->RBuffer[plci->req_out-1] = 0;
8788       l+=3;
8789       plci->nl_global_req = plci->nl_req;
8790     }
8791     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8792   }
8793   else
8794   {
8795     e = &plci->Sig;
8796     if(plci->RBuffer[plci->req_out])
8797       e->Id = plci->RBuffer[plci->req_out];
8798     plci->req_out++;
8799     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8800     e->ReqCh = plci->RBuffer[plci->req_out++];
8801     if(!(e->Id & 0x1f))
8802       plci->sig_global_req = plci->sig_req;
8803     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8804   }
8805   plci->XData[0].PLength = l;
8806   e->X = plci->XData;
8807   plci->adapter->request(e);
8808   dbug(1,dprintf("send_ok"));
8809 }
8810
8811 static void send_data(PLCI *plci)
8812 {
8813   DIVA_CAPI_ADAPTER   * a;
8814   DATA_B3_DESC   * data;
8815   NCCI   *ncci_ptr;
8816   word ncci;
8817
8818   if (!plci->nl_req && plci->ncci_ring_list)
8819   {
8820     a = plci->adapter;
8821     ncci = plci->ncci_ring_list;
8822     do
8823     {
8824       ncci = a->ncci_next[ncci];
8825       ncci_ptr = &(a->ncci[ncci]);
8826       if (!(a->ncci_ch[ncci]
8827          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8828       {
8829         if (ncci_ptr->data_pending)
8830         {
8831           if ((a->ncci_state[ncci] == CONNECTED)
8832            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8833            || (plci->send_disc == ncci))
8834           {
8835             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8836             if ((plci->B2_prot == B2_V120_ASYNC)
8837              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8838              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8839             {
8840               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8841               plci->NData[1].PLength = data->Length;
8842               if (data->Flags & 0x10)
8843                 plci->NData[0].P = v120_break_header;
8844               else
8845                 plci->NData[0].P = v120_default_header;
8846               plci->NData[0].PLength = 1 ;
8847               plci->NL.XNum = 2;
8848               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8849             }
8850             else
8851             {
8852               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8853               plci->NData[0].PLength = data->Length;
8854               if (data->Flags & 0x10)
8855                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8856
8857               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8858                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8859
8860               else
8861                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8862             }
8863             plci->NL.X = plci->NData;
8864             plci->NL.ReqCh = a->ncci_ch[ncci];
8865             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8866             plci->data_sent = true;
8867             plci->data_sent_ptr = data->P;
8868             a->request(&plci->NL);
8869           }
8870           else {
8871             cleanup_ncci_data (plci, ncci);
8872           }
8873         }
8874         else if (plci->send_disc == ncci)
8875         {
8876           /* dprintf("N_DISC"); */
8877           plci->NData[0].PLength = 0;
8878           plci->NL.ReqCh = a->ncci_ch[ncci];
8879           plci->NL.Req = plci->nl_req = N_DISC;
8880           a->request(&plci->NL);
8881           plci->command = _DISCONNECT_B3_R;
8882           plci->send_disc = 0;
8883         }
8884       }
8885     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8886     plci->ncci_ring_list = ncci;
8887   }
8888 }
8889
8890 static void listen_check(DIVA_CAPI_ADAPTER *a)
8891 {
8892   word i,j;
8893   PLCI   * plci;
8894   byte activnotifiedcalls = 0;
8895
8896   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8897   if (!remove_started && !a->adapter_disabled)
8898   {
8899     for(i=0;i<a->max_plci;i++)
8900     {
8901       plci = &(a->plci[i]);
8902       if(plci->notifiedcall) activnotifiedcalls++;
8903     }
8904     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8905
8906     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8907       if((j=get_plci(a))) {
8908         a->listen_active++;
8909         plci = &a->plci[j-1];
8910         plci->State = LISTENING;
8911
8912         add_p(plci,OAD,"\x01\xfd");
8913
8914         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8915
8916         add_p(plci,CAI,"\x01\xc0");
8917         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8918         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8919         add_p(plci,SHIFT|6,NULL);
8920         add_p(plci,SIN,"\x02\x00\x00");
8921         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8922         sig_req(plci,ASSIGN,DSIG_ID);
8923         send_req(plci);
8924       }
8925     }
8926   }
8927 }
8928
8929 /*------------------------------------------------------------------*/
8930 /* functions for all parameters sent in INDs                        */
8931 /*------------------------------------------------------------------*/
8932
8933 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8934 {
8935   word ploc;            /* points to current location within packet */
8936   byte w;
8937   byte wlen;
8938   byte codeset,lock;
8939   byte   * in;
8940   word i;
8941   word code;
8942   word mIEindex = 0;
8943   ploc = 0;
8944   codeset = 0;
8945   lock = 0;
8946
8947   in = plci->Sig.RBuffer->P;
8948   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8949   {                            /* element but parms array is larger      */
8950     parms[i] = (byte   *)"";
8951   }
8952   for(i=0; i<multiIEsize; i++)
8953   {
8954     parms[i] = (byte   *)"";
8955   }
8956
8957   while(ploc<plci->Sig.RBuffer->length-1) {
8958
8959         /* read information element id and length                   */
8960     w = in[ploc];
8961
8962     if(w & 0x80) {
8963 /*    w &=0xf0; removed, cannot detect congestion levels */
8964 /*    upper 4 bit masked with w==SHIFT now               */
8965       wlen = 0;
8966     }
8967     else {
8968       wlen = (byte)(in[ploc+1]+1);
8969     }
8970         /* check if length valid (not exceeding end of packet)      */
8971     if((ploc+wlen) > 270) return ;
8972     if(lock & 0x80) lock &=0x7f;
8973     else codeset = lock;
8974
8975     if((w&0xf0)==SHIFT) {
8976       codeset = in[ploc];
8977       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8978       codeset &=7;
8979       lock |=0x80;
8980     }
8981     else {
8982       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8983       else code = w;
8984       code |= (codeset<<8);
8985
8986       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8987
8988       if(i<parms_id[0]+1) {
8989         if(!multiIEsize) { /* with multiIEs use next field index,          */
8990           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8991         }
8992
8993         parms[mIEindex] = &in[ploc+1];
8994         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8995         if(parms_id[i]==OAD
8996         || parms_id[i]==CONN_NR
8997         || parms_id[i]==CAD) {
8998           if(in[ploc+2] &0x80) {
8999             in[ploc+0] = (byte)(in[ploc+1]+1);
9000             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
9001             in[ploc+2] = 0x80;
9002             parms[mIEindex] = &in[ploc];
9003           }
9004         }
9005         mIEindex++;       /* effects multiIEs only */
9006       }
9007     }
9008
9009     ploc +=(wlen+1);
9010   }
9011   return ;
9012 }
9013
9014 /*------------------------------------------------------------------*/
9015 /* try to match a cip from received BC and HLC                      */
9016 /*------------------------------------------------------------------*/
9017
9018 static byte ie_compare(byte *ie1, byte *ie2)
9019 {
9020   word i;
9021   if(!ie1 || ! ie2) return false;
9022   if(!ie1[0]) return false;
9023   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9024   return true;
9025 }
9026
9027 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9028 {
9029   word i;
9030   word j;
9031
9032   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9033
9034   for(j=16;j<29 &&
9035            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9036   if(j==29) return i;
9037   return j;
9038 }
9039
9040
9041 static byte AddInfo(byte   **add_i,
9042                     byte   **fty_i,
9043                     byte   *esc_chi,
9044                     byte *facility)
9045 {
9046   byte i;
9047   byte j;
9048   byte k;
9049   byte flen;
9050   byte len=0;
9051    /* facility is a nested structure */
9052    /* FTY can be more than once      */
9053
9054         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9055   {
9056     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9057   }
9058
9059   else
9060   {
9061     add_i[0] = (byte   *)"";
9062   }
9063   if(!fty_i[0][0])
9064   {
9065     add_i[3] = (byte   *)"";
9066   }
9067   else
9068   {    /* facility array found  */
9069     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9070     {
9071       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9072       len += fty_i[i][0];
9073       len += 2;
9074       flen=fty_i[i][0];
9075       facility[j++]=0x1c; /* copy fac IE */
9076       for(k=0;k<=flen;k++,j++)
9077       {
9078         facility[j]=fty_i[i][k];
9079 /*      dbug(1,dprintf("%x ",facility[j])); */
9080       }
9081     }
9082     facility[0] = len;
9083     add_i[3] = facility;
9084   }
9085 /*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9086   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9087   len += 4;                          /* calculate length of all */
9088   return(len);
9089 }
9090
9091 /*------------------------------------------------------------------*/
9092 /* voice and codec features                                         */
9093 /*------------------------------------------------------------------*/
9094
9095 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9096 {
9097   byte voice_chi[] = "\x02\x18\x01";
9098   byte channel;
9099
9100   channel = chi[chi[0]]&0x3;
9101   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9102   voice_chi[2] = (channel) ? channel : 1;
9103   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9104   add_p(plci,ESC,voice_chi);                  /* Channel */
9105   sig_req(plci,TEL_CTRL,0);
9106   send_req(plci);
9107   if(a->AdvSignalPLCI)
9108   {
9109     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9110   }
9111 }
9112
9113 static void VoiceChannelOff(PLCI *plci)
9114 {
9115   dbug(1,dprintf("ExtDevOFF"));
9116   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9117   sig_req(plci,TEL_CTRL,0);
9118   send_req(plci);
9119   if(plci->adapter->AdvSignalPLCI)
9120   {
9121     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9122   }
9123 }
9124
9125
9126 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9127                             byte hook_listen)
9128 {
9129   word j;
9130   PLCI   *splci;
9131
9132   /* check if hardware supports handset with hook states (adv.codec) */
9133   /* or if just a on board codec is supported                        */
9134   /* the advanced codec plci is just for internal use                */
9135
9136   /* diva Pro with on-board codec:                                   */
9137   if(a->profile.Global_Options & HANDSET)
9138   {
9139     /* new call, but hook states are already signalled */
9140     if(a->AdvCodecFLAG)
9141     {
9142       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9143       {
9144         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9145         return 0x2001; /* codec in use by another application */
9146       }
9147       if(plci!=NULL)
9148       {
9149         a->AdvSignalPLCI = plci;
9150         plci->tel=ADV_VOICE;
9151       }
9152       return 0;                      /* adv codec still used */
9153     }
9154     if((j=get_plci(a)))
9155     {
9156       splci = &a->plci[j-1];
9157       splci->tel = CODEC_PERMANENT;
9158       /* hook_listen indicates if a facility_req with handset/hook support */
9159       /* was sent. Otherwise if just a call on an external device was made */
9160       /* the codec will be used but the hook info will be discarded (just  */
9161       /* the external controller is in use                                 */
9162       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9163       else
9164       {
9165         splci->State = ADVANCED_VOICE_NOSIG;
9166         if(plci)
9167         {
9168           plci->spoofed_msg = SPOOFING_REQUIRED;
9169         }
9170                                                /* indicate D-ch connect if  */
9171       }                                        /* codec is connected OK     */
9172       if(plci!=NULL)
9173       {
9174         a->AdvSignalPLCI = plci;
9175         plci->tel=ADV_VOICE;
9176       }
9177       a->AdvSignalAppl = appl;
9178       a->AdvCodecFLAG = true;
9179       a->AdvCodecPLCI = splci;
9180       add_p(splci,CAI,"\x01\x15");
9181       add_p(splci,LLI,"\x01\x00");
9182       add_p(splci,ESC,"\x02\x18\x00");
9183       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184       splci->internal_command = PERM_COD_ASSIGN;
9185       dbug(1,dprintf("Codec Assign"));
9186       sig_req(splci,ASSIGN,DSIG_ID);
9187       send_req(splci);
9188     }
9189     else
9190     {
9191       return 0x2001; /* wrong state, no more plcis */
9192     }
9193   }
9194   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9195   {
9196     if(hook_listen) return 0x300B;               /* Facility not supported */
9197                                                  /* no hook with SCOM      */
9198     if(plci!=NULL) plci->tel = CODEC;
9199     dbug(1,dprintf("S/SCOM codec"));
9200     /* first time we use the scom-s codec we must shut down the internal   */
9201     /* handset application of the card. This can be done by an assign with */
9202     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9203     if(!a->scom_appl_disable){
9204       if((j=get_plci(a))) {
9205         splci = &a->plci[j-1];
9206         add_p(splci,CAI,"\x01\x80");
9207         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9208         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9209         send_req(splci);
9210         a->scom_appl_disable = true;
9211       }
9212       else{
9213         return 0x2001; /* wrong state, no more plcis */
9214       }
9215     }
9216   }
9217   else return 0x300B;               /* Facility not supported */
9218
9219   return 0;
9220 }
9221
9222
9223 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9224 {
9225
9226   dbug(1,dprintf("CodecIdCheck"));
9227
9228   if(a->AdvSignalPLCI == plci)
9229   {
9230     dbug(1,dprintf("PLCI owns codec"));
9231     VoiceChannelOff(a->AdvCodecPLCI);
9232     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9233     {
9234       dbug(1,dprintf("remove temp codec PLCI"));
9235       plci_remove(a->AdvCodecPLCI);
9236       a->AdvCodecFLAG  = 0;
9237       a->AdvCodecPLCI  = NULL;
9238       a->AdvSignalAppl = NULL;
9239     }
9240     a->AdvSignalPLCI = NULL;
9241   }
9242 }
9243
9244 /* -------------------------------------------------------------------
9245     Ask for physical address of card on PCI bus
9246    ------------------------------------------------------------------- */
9247 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9248                                         IDI_SYNC_REQ  * preq) {
9249   a->sdram_bar = 0;
9250   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9251     ENTITY   * e = (ENTITY   *)preq;
9252
9253     e->user[0] = a->Id - 1;
9254     preq->xdi_sdram_bar.info.bar    = 0;
9255     preq->xdi_sdram_bar.Req         = 0;
9256     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9257
9258     (*(a->request))(e);
9259
9260     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9261     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9262   }
9263 }
9264
9265 /* -------------------------------------------------------------------
9266      Ask XDI about extended features
9267    ------------------------------------------------------------------- */
9268 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9269   IDI_SYNC_REQ   * preq;
9270     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9271
9272     char features[4];
9273   preq = (IDI_SYNC_REQ   *)&buffer[0];
9274
9275   if (!diva_xdi_extended_features) {
9276     ENTITY   * e = (ENTITY   *)preq;
9277     diva_xdi_extended_features |= 0x80000000;
9278
9279     e->user[0] = a->Id - 1;
9280     preq->xdi_extended_features.Req = 0;
9281     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9282     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9283     preq->xdi_extended_features.info.features = &features[0];
9284
9285     (*(a->request))(e);
9286
9287     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9288       /*
9289          Check features located in the byte '0'
9290          */
9291       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9292         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9293       }
9294       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9295         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9296         dbug(1,dprintf("XDI provides RxDMA"));
9297       }
9298       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9299         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9300       }
9301       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9302         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9303         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9304       }
9305
9306     }
9307   }
9308
9309   diva_ask_for_xdi_sdram_bar (a, preq);
9310 }
9311
9312 /*------------------------------------------------------------------*/
9313 /* automatic law                                                    */
9314 /*------------------------------------------------------------------*/
9315 /* called from OS specific part after init time to get the Law              */
9316 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9317 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9318 {
9319   word j;
9320   PLCI   *splci;
9321
9322   if(a->automatic_law) {
9323     return;
9324   }
9325   if((j=get_plci(a))) {
9326     diva_get_extended_adapter_features (a);
9327     splci = &a->plci[j-1];
9328     a->automatic_lawPLCI = splci;
9329     a->automatic_law = 1;
9330     add_p(splci,CAI,"\x01\x80");
9331     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9332     splci->internal_command = USELAW_REQ;
9333     splci->command = 0;
9334     splci->number = 0;
9335     sig_req(splci,ASSIGN,DSIG_ID);
9336     send_req(splci);
9337   }
9338 }
9339
9340 /* called from OS specific part if an application sends an Capi20Release */
9341 word CapiRelease(word Id)
9342 {
9343   word i, j, appls_found;
9344   PLCI   *plci;
9345   APPL   *this;
9346   DIVA_CAPI_ADAPTER   *a;
9347
9348   if (!Id)
9349   {
9350     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9351     return (_WRONG_APPL_ID);
9352   }
9353
9354   this = &application[Id-1];               /* get application pointer */
9355
9356   for(i=0,appls_found=0; i<max_appl; i++)
9357   {
9358     if(application[i].Id)       /* an application has been found        */
9359     {
9360       appls_found++;
9361     }
9362   }
9363
9364   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9365   {
9366     a = &adapter[i];
9367     if (a->request)
9368     {
9369       a->Info_Mask[Id-1] = 0;
9370       a->CIP_Mask[Id-1] = 0;
9371       a->Notification_Mask[Id-1] = 0;
9372       a->codec_listen[Id-1] = NULL;
9373       a->requested_options_table[Id-1] = 0;
9374       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9375       {                                      /* with this application   */
9376         plci = &a->plci[j];
9377         if(plci->Id)                         /* if plci owns no application */
9378         {                                    /* it may be not jet connected */
9379           if(plci->State==INC_CON_PENDING
9380           || plci->State==INC_CON_ALERT)
9381           {
9382             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9383             {
9384               clear_c_ind_mask_bit (plci, (word)(Id-1));
9385               if(c_ind_mask_empty (plci))
9386               {
9387                 sig_req(plci,HANGUP,0);
9388                 send_req(plci);
9389                 plci->State = OUTG_DIS_PENDING;
9390               }
9391             }
9392           }
9393           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9394           {
9395             clear_c_ind_mask_bit (plci, (word)(Id-1));
9396             if(c_ind_mask_empty (plci))
9397             {
9398               if(!plci->appl)
9399               {
9400                 plci_remove(plci);
9401                 plci->State = IDLE;
9402               }
9403             }
9404           }
9405           if(plci->appl==this)
9406           {
9407             plci->appl = NULL;
9408             plci_remove(plci);
9409             plci->State = IDLE;
9410           }
9411         }
9412       }
9413       listen_check(a);
9414
9415       if(a->flag_dynamic_l1_down)
9416       {
9417         if(appls_found==1)            /* last application does a capi release */
9418         {
9419           if((j=get_plci(a)))
9420           {
9421             plci = &a->plci[j-1];
9422             plci->command = 0;
9423             add_p(plci,OAD,"\x01\xfd");
9424             add_p(plci,CAI,"\x01\x80");
9425             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9426             add_p(plci,SHIFT|6,NULL);
9427             add_p(plci,SIN,"\x02\x00\x00");
9428             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9429             sig_req(plci,ASSIGN,DSIG_ID);
9430             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9431             sig_req(plci,SIG_CTRL,0);
9432             send_req(plci);
9433           }
9434         }
9435       }
9436       if(a->AdvSignalAppl==this)
9437       {
9438         this->NullCREnable = false;
9439         if (a->AdvCodecPLCI)
9440         {
9441           plci_remove(a->AdvCodecPLCI);
9442           a->AdvCodecPLCI->tel = 0;
9443           a->AdvCodecPLCI->adv_nl = 0;
9444         }
9445         a->AdvSignalAppl = NULL;
9446         a->AdvSignalPLCI = NULL;
9447         a->AdvCodecFLAG = 0;
9448         a->AdvCodecPLCI = NULL;
9449       }
9450     }
9451   }
9452
9453   this->Id = 0;
9454
9455   return GOOD;
9456 }
9457
9458 static word plci_remove_check(PLCI   *plci)
9459 {
9460   if(!plci) return true;
9461   if(!plci->NL.Id && c_ind_mask_empty (plci))
9462   {
9463     if(plci->Sig.Id == 0xff)
9464       plci->Sig.Id = 0;
9465     if(!plci->Sig.Id)
9466     {
9467       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9468       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9469       if (plci->Id)
9470       {
9471         CodecIdCheck(plci->adapter, plci);
9472         clear_b1_config (plci);
9473         ncci_remove (plci, 0, false);
9474         plci_free_msg_in_queue (plci);
9475         channel_flow_control_remove (plci);
9476         plci->Id = 0;
9477         plci->State = IDLE;
9478         plci->channels = 0;
9479         plci->appl = NULL;
9480         plci->notifiedcall = 0;
9481       }
9482       listen_check(plci->adapter);
9483       return true;
9484     }
9485   }
9486   return false;
9487 }
9488
9489
9490 /*------------------------------------------------------------------*/
9491
9492 static byte plci_nl_busy (PLCI   *plci)
9493 {
9494   /* only applicable for non-multiplexed protocols */
9495   return (plci->nl_req
9496     || (plci->ncci_ring_list
9497      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9498      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9499 }
9500
9501
9502 /*------------------------------------------------------------------*/
9503 /* DTMF facilities                                                  */
9504 /*------------------------------------------------------------------*/
9505
9506
9507 static struct
9508 {
9509   byte send_mask;
9510   byte listen_mask;
9511   byte character;
9512   byte code;
9513 } dtmf_digit_map[] =
9514 {
9515   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9516   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9517   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9518   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9519   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9520   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9521   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9522   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9523   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9524   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9525   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9526   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9527   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9528   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9529   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9530   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9531   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9532   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9533   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9534   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9535
9536   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9537   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9538   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9539   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9540   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9541   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9542   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9543   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9544   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9545   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9546   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9547   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9548   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9549   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9550   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9551   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9552   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9553   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9554   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9555   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9556   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9557   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9558   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9559   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9560   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9561   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9562   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9563   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9564   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9565   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9566   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9567   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9568   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9569   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9570   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9571   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9572   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9573   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9574   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9575   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9576   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9577   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9578   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9579   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9580   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9581   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9582   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9583   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9584   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9585   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9586   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9587   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9588
9589 };
9590
9591 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9592
9593
9594 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9595 {
9596   word min_digit_duration, min_gap_duration;
9597
9598   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9599     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9600     (char   *)(FILE_), __LINE__, enable_mask));
9601
9602   if (enable_mask != 0)
9603   {
9604     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9605     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9606     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9607     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9608     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9609     plci->NData[0].PLength = 5;
9610
9611     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9612     plci->NData[0].PLength += 2;
9613     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9614
9615   }
9616   else
9617   {
9618     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9619     plci->NData[0].PLength = 1;
9620
9621     capidtmf_recv_disable (&(plci->capidtmf_state));
9622
9623   }
9624   plci->NData[0].P = plci->internal_req_buffer;
9625   plci->NL.X = plci->NData;
9626   plci->NL.ReqCh = 0;
9627   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9628   plci->adapter->request (&plci->NL);
9629 }
9630
9631
9632 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9633 {
9634   word w, i;
9635
9636   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9637     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9638     (char   *)(FILE_), __LINE__, digit_count));
9639
9640   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9641   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9642   PUT_WORD (&plci->internal_req_buffer[1], w);
9643   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9644   PUT_WORD (&plci->internal_req_buffer[3], w);
9645   for (i = 0; i < digit_count; i++)
9646   {
9647     w = 0;
9648     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9649       && (digit_buffer[i] != dtmf_digit_map[w].character))
9650     {
9651       w++;
9652     }
9653     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9654       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9655   }
9656   plci->NData[0].PLength = 5 + digit_count;
9657   plci->NData[0].P = plci->internal_req_buffer;
9658   plci->NL.X = plci->NData;
9659   plci->NL.ReqCh = 0;
9660   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9661   plci->adapter->request (&plci->NL);
9662 }
9663
9664
9665 static void dtmf_rec_clear_config (PLCI   *plci)
9666 {
9667
9668   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9669     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9670     (char   *)(FILE_), __LINE__));
9671
9672   plci->dtmf_rec_active = 0;
9673   plci->dtmf_rec_pulse_ms = 0;
9674   plci->dtmf_rec_pause_ms = 0;
9675
9676   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9677
9678 }
9679
9680
9681 static void dtmf_send_clear_config (PLCI   *plci)
9682 {
9683
9684   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9685     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9686     (char   *)(FILE_), __LINE__));
9687
9688   plci->dtmf_send_requests = 0;
9689   plci->dtmf_send_pulse_ms = 0;
9690   plci->dtmf_send_pause_ms = 0;
9691 }
9692
9693
9694 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9695 {
9696
9697   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9698     UnMapId (Id), (char   *)(FILE_), __LINE__));
9699
9700   while (plci->dtmf_send_requests != 0)
9701     dtmf_confirmation (Id, plci);
9702 }
9703
9704
9705 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9706 {
9707
9708   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9709     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9710
9711   return (GOOD);
9712 }
9713
9714
9715 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9716 {
9717   word Info;
9718
9719   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9720     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9721
9722   Info = GOOD;
9723   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9724   {
9725     switch (plci->adjust_b_state)
9726     {
9727     case ADJUST_B_RESTORE_DTMF_1:
9728       plci->internal_command = plci->adjust_b_command;
9729       if (plci_nl_busy (plci))
9730       {
9731         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9732         break;
9733       }
9734       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9735       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9736       break;
9737     case ADJUST_B_RESTORE_DTMF_2:
9738       if ((Rc != OK) && (Rc != OK_FC))
9739       {
9740         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9741           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9742         Info = _WRONG_STATE;
9743         break;
9744       }
9745       break;
9746     }
9747   }
9748   return (Info);
9749 }
9750
9751
9752 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9753 {
9754   word internal_command, Info;
9755   byte mask;
9756     byte result[4];
9757
9758   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9759     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9760     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9761     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9762
9763   Info = GOOD;
9764   result[0] = 2;
9765   PUT_WORD (&result[1], DTMF_SUCCESS);
9766   internal_command = plci->internal_command;
9767   plci->internal_command = 0;
9768   mask = 0x01;
9769   switch (plci->dtmf_cmd)
9770   {
9771
9772   case DTMF_LISTEN_TONE_START:
9773     mask <<= 1;
9774   case DTMF_LISTEN_MF_START:
9775     mask <<= 1;
9776
9777   case DTMF_LISTEN_START:
9778     switch (internal_command)
9779     {
9780     default:
9781       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9782         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9783     case DTMF_COMMAND_1:
9784       if (adjust_b_process (Id, plci, Rc) != GOOD)
9785       {
9786         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9787           UnMapId (Id), (char   *)(FILE_), __LINE__));
9788         Info = _FACILITY_NOT_SUPPORTED;
9789         break;
9790       }
9791       if (plci->internal_command)
9792         return;
9793     case DTMF_COMMAND_2:
9794       if (plci_nl_busy (plci))
9795       {
9796         plci->internal_command = DTMF_COMMAND_2;
9797         return;
9798       }
9799       plci->internal_command = DTMF_COMMAND_3;
9800       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9801       return;
9802     case DTMF_COMMAND_3:
9803       if ((Rc != OK) && (Rc != OK_FC))
9804       {
9805         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9806           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9807         Info = _FACILITY_NOT_SUPPORTED;
9808         break;
9809       }
9810
9811       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9812
9813       plci->dtmf_rec_active |= mask;
9814       break;
9815     }
9816     break;
9817
9818
9819   case DTMF_LISTEN_TONE_STOP:
9820     mask <<= 1;
9821   case DTMF_LISTEN_MF_STOP:
9822     mask <<= 1;
9823
9824   case DTMF_LISTEN_STOP:
9825     switch (internal_command)
9826     {
9827     default:
9828       plci->dtmf_rec_active &= ~mask;
9829       if (plci->dtmf_rec_active)
9830         break;
9831 /*
9832     case DTMF_COMMAND_1:
9833       if (plci->dtmf_rec_active)
9834       {
9835         if (plci_nl_busy (plci))
9836         {
9837           plci->internal_command = DTMF_COMMAND_1;
9838           return;
9839         }
9840         plci->dtmf_rec_active &= ~mask;
9841         plci->internal_command = DTMF_COMMAND_2;
9842         dtmf_enable_receiver (plci, false);
9843         return;
9844       }
9845       Rc = OK;
9846     case DTMF_COMMAND_2:
9847       if ((Rc != OK) && (Rc != OK_FC))
9848       {
9849         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9850           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9851         Info = _FACILITY_NOT_SUPPORTED;
9852         break;
9853       }
9854 */
9855       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9856         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9857     case DTMF_COMMAND_3:
9858       if (adjust_b_process (Id, plci, Rc) != GOOD)
9859       {
9860         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9861           UnMapId (Id), (char   *)(FILE_), __LINE__));
9862         Info = _FACILITY_NOT_SUPPORTED;
9863         break;
9864       }
9865       if (plci->internal_command)
9866         return;
9867       break;
9868     }
9869     break;
9870
9871
9872   case DTMF_SEND_TONE:
9873     mask <<= 1;
9874   case DTMF_SEND_MF:
9875     mask <<= 1;
9876
9877   case DTMF_DIGITS_SEND:
9878     switch (internal_command)
9879     {
9880     default:
9881       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9882         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9883         DTMF_COMMAND_1);
9884     case DTMF_COMMAND_1:
9885       if (adjust_b_process (Id, plci, Rc) != GOOD)
9886       {
9887         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9888           UnMapId (Id), (char   *)(FILE_), __LINE__));
9889         Info = _FACILITY_NOT_SUPPORTED;
9890         break;
9891       }
9892       if (plci->internal_command)
9893         return;
9894     case DTMF_COMMAND_2:
9895       if (plci_nl_busy (plci))
9896       {
9897         plci->internal_command = DTMF_COMMAND_2;
9898         return;
9899       }
9900       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9901       plci->internal_command = DTMF_COMMAND_3;
9902       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9903       return;
9904     case DTMF_COMMAND_3:
9905       if ((Rc != OK) && (Rc != OK_FC))
9906       {
9907         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9908           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9909         if (plci->dtmf_send_requests != 0)
9910           (plci->dtmf_send_requests)--;
9911         Info = _FACILITY_NOT_SUPPORTED;
9912         break;
9913       }
9914       return;
9915     }
9916     break;
9917   }
9918   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9919     "wws", Info, SELECTOR_DTMF, result);
9920 }
9921
9922
9923 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9924 {
9925   word Info;
9926   word i, j;
9927   byte mask;
9928     API_PARSE dtmf_parms[5];
9929     byte result[40];
9930
9931   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9932     UnMapId (Id), (char   *)(FILE_), __LINE__));
9933
9934   Info = GOOD;
9935   result[0] = 2;
9936   PUT_WORD (&result[1], DTMF_SUCCESS);
9937   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9938   {
9939     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9940       UnMapId (Id), (char   *)(FILE_), __LINE__));
9941     Info = _FACILITY_NOT_SUPPORTED;
9942   }
9943   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9944   {
9945     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9946       UnMapId (Id), (char   *)(FILE_), __LINE__));
9947     Info = _WRONG_MESSAGE_FORMAT;
9948   }
9949
9950   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9951     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9952   {
9953     if (!((a->requested_options_table[appl->Id-1])
9954         & (1L << PRIVATE_DTMF_TONE)))
9955     {
9956       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9957         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9958       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9959     }
9960     else
9961     {
9962       for (i = 0; i < 32; i++)
9963         result[4 + i] = 0;
9964       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9965       {
9966         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9967         {
9968           if (dtmf_digit_map[i].listen_mask != 0)
9969             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9970         }
9971       }
9972       else
9973       {
9974         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9975         {
9976           if (dtmf_digit_map[i].send_mask != 0)
9977             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9978         }
9979       }
9980       result[0] = 3 + 32;
9981       result[3] = 32;
9982     }
9983   }
9984
9985   else if (plci == NULL)
9986   {
9987     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9988       UnMapId (Id), (char   *)(FILE_), __LINE__));
9989     Info = _WRONG_IDENTIFIER;
9990   }
9991   else
9992   {
9993     if (!plci->State
9994      || !plci->NL.Id || plci->nl_remove_id)
9995     {
9996       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9997         UnMapId (Id), (char   *)(FILE_), __LINE__));
9998       Info = _WRONG_STATE;
9999     }
10000     else
10001     {
10002       plci->command = 0;
10003       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
10004       mask = 0x01;
10005       switch (plci->dtmf_cmd)
10006       {
10007
10008       case DTMF_LISTEN_TONE_START:
10009       case DTMF_LISTEN_TONE_STOP:
10010         mask <<= 1;
10011       case DTMF_LISTEN_MF_START:
10012       case DTMF_LISTEN_MF_STOP:
10013         mask <<= 1;
10014         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10015           & (1L << PRIVATE_DTMF_TONE)))
10016         {
10017           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10018             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10019           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10020           break;
10021         }
10022
10023       case DTMF_LISTEN_START:
10024       case DTMF_LISTEN_STOP:
10025         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10026          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10027         {
10028           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10029             UnMapId (Id), (char   *)(FILE_), __LINE__));
10030           Info = _FACILITY_NOT_SUPPORTED;
10031           break;
10032         }
10033         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10034         {
10035           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10036           {
10037             plci->dtmf_rec_pulse_ms = 0;
10038             plci->dtmf_rec_pause_ms = 0;
10039           }
10040           else
10041           {
10042             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10043             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10044           }
10045         }
10046         start_internal_command (Id, plci, dtmf_command);
10047         return (false);
10048
10049
10050       case DTMF_SEND_TONE:
10051         mask <<= 1;
10052       case DTMF_SEND_MF:
10053         mask <<= 1;
10054         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10055           & (1L << PRIVATE_DTMF_TONE)))
10056         {
10057           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10058             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10059           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10060           break;
10061         }
10062
10063       case DTMF_DIGITS_SEND:
10064         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10065         {
10066           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10067             UnMapId (Id), (char   *)(FILE_), __LINE__));
10068           Info = _WRONG_MESSAGE_FORMAT;
10069           break;
10070         }
10071         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10072         {
10073           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10074           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10075         }
10076         i = 0;
10077         j = 0;
10078         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10079         {
10080           j = 0;
10081           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10082             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10083              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10084           {
10085             j++;
10086           }
10087           i++;
10088         }
10089         if (j == DTMF_DIGIT_MAP_ENTRIES)
10090         {
10091           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10092             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10093           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10094           break;
10095         }
10096         if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10097         {
10098           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10099             UnMapId (Id), (char   *)(FILE_), __LINE__));
10100           Info = _WRONG_STATE;
10101           break;
10102         }
10103         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10104         start_internal_command (Id, plci, dtmf_command);
10105         return (false);
10106
10107       default:
10108         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10109           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10110         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10111       }
10112     }
10113   }
10114   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10115     "wws", Info, SELECTOR_DTMF, result);
10116   return (false);
10117 }
10118
10119
10120 static void dtmf_confirmation (dword Id, PLCI   *plci)
10121 {
10122   word Info;
10123   word i;
10124     byte result[4];
10125
10126   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10127     UnMapId (Id), (char   *)(FILE_), __LINE__));
10128
10129   Info = GOOD;
10130   result[0] = 2;
10131   PUT_WORD (&result[1], DTMF_SUCCESS);
10132   if (plci->dtmf_send_requests != 0)
10133   {
10134     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10135       "wws", GOOD, SELECTOR_DTMF, result);
10136     (plci->dtmf_send_requests)--;
10137     for (i = 0; i < plci->dtmf_send_requests; i++)
10138       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10139   }
10140 }
10141
10142
10143 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10144 {
10145   word i, j, n;
10146
10147   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10148     UnMapId (Id), (char   *)(FILE_), __LINE__));
10149
10150   n = 0;
10151   for (i = 1; i < length; i++)
10152   {
10153     j = 0;
10154     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10155       && ((msg[i] != dtmf_digit_map[j].code)
10156        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10157     {
10158       j++;
10159     }
10160     if (j < DTMF_DIGIT_MAP_ENTRIES)
10161     {
10162
10163       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10164        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10165        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10166       {
10167         if (n + 1 == i)
10168         {
10169           for (i = length; i > n + 1; i--)
10170             msg[i] = msg[i - 1];
10171           length++;
10172           i++;
10173         }
10174         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10175       }
10176       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10177
10178       msg[++n] = dtmf_digit_map[j].character;
10179     }
10180   }
10181   if (n != 0)
10182   {
10183     msg[0] = (byte) n;
10184     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10185   }
10186 }
10187
10188
10189 /*------------------------------------------------------------------*/
10190 /* DTMF parameters                                                  */
10191 /*------------------------------------------------------------------*/
10192
10193 static void dtmf_parameter_write (PLCI   *plci)
10194 {
10195   word i;
10196     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10197
10198   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10199     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10200     (char   *)(FILE_), __LINE__));
10201
10202   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10203   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10204   for (i = 0; i < plci->dtmf_parameter_length; i++)
10205     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10206   add_p (plci, FTY, parameter_buffer);
10207   sig_req (plci, TEL_CTRL, 0);
10208   send_req (plci);
10209 }
10210
10211
10212 static void dtmf_parameter_clear_config (PLCI   *plci)
10213 {
10214
10215   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10216     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10217     (char   *)(FILE_), __LINE__));
10218
10219   plci->dtmf_parameter_length = 0;
10220 }
10221
10222
10223 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10224 {
10225
10226   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10227     UnMapId (Id), (char   *)(FILE_), __LINE__));
10228
10229 }
10230
10231
10232 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10233 {
10234
10235   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10236     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10237
10238   return (GOOD);
10239 }
10240
10241
10242 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10243 {
10244   word Info;
10245
10246   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10247     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10248
10249   Info = GOOD;
10250   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10251    && (plci->dtmf_parameter_length != 0))
10252   {
10253     switch (plci->adjust_b_state)
10254     {
10255     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10256       plci->internal_command = plci->adjust_b_command;
10257       if (plci->sig_req)
10258       {
10259         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10260         break;
10261       }
10262       dtmf_parameter_write (plci);
10263       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10264       break;
10265     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10266       if ((Rc != OK) && (Rc != OK_FC))
10267       {
10268         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10269           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10270         Info = _WRONG_STATE;
10271         break;
10272       }
10273       break;
10274     }
10275   }
10276   return (Info);
10277 }
10278
10279
10280 /*------------------------------------------------------------------*/
10281 /* Line interconnect facilities                                     */
10282 /*------------------------------------------------------------------*/
10283
10284
10285 LI_CONFIG   *li_config_table;
10286 word li_total_channels;
10287
10288
10289 /*------------------------------------------------------------------*/
10290 /* translate a CHI information element to a channel number          */
10291 /* returns 0xff - any channel                                       */
10292 /*         0xfe - chi wrong coding                                  */
10293 /*         0xfd - D-channel                                         */
10294 /*         0x00 - no channel                                        */
10295 /*         else channel number / PRI: timeslot                      */
10296 /* if channels is provided we accept more than one channel.         */
10297 /*------------------------------------------------------------------*/
10298
10299 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10300 {
10301   int p;
10302   int i;
10303   dword map;
10304   byte excl;
10305   byte ofs;
10306   byte ch;
10307
10308   if (pchannelmap) *pchannelmap = 0;
10309   if(!chi[0]) return 0xff;
10310   excl = 0;
10311
10312   if(chi[1] & 0x20) {
10313     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10314     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10315     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10316     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10317     if(chi[1] &0x08) excl = 0x40;
10318
10319         /* int. id present */
10320     if(chi[1] &0x40) {
10321       p=i+1;
10322       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10323       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10324     }
10325
10326         /* coding standard, Number/Map, Channel Type */
10327     p=i+1;
10328     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10329     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10330     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10331
10332         /* Number/Map */
10333     if(chi[p] &0x10) {
10334
10335         /* map */
10336       if((chi[0]-p)==4) ofs = 0;
10337       else if((chi[0]-p)==3) ofs = 1;
10338       else return 0xfe;
10339       ch = 0;
10340       map = 0;
10341       for(i=0; i<4 && p<chi[0]; i++) {
10342         p++;
10343         ch += 8;
10344         map <<= 8;
10345         if(chi[p]) {
10346           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10347           map |= chi[p];
10348         }
10349       }
10350       ch += ofs;
10351       map <<= ofs;
10352     }
10353     else {
10354
10355         /* number */
10356       p=i+1;
10357       ch = chi[p] &0x3f;
10358       if(pchannelmap) {
10359         if((byte)(chi[0]-p)>30) return 0xfe;
10360         map = 0;
10361         for(i=p; i<=chi[0]; i++) {
10362           if ((chi[i] &0x7f) > 31) return 0xfe;
10363           map |= (1L << (chi[i] &0x7f));
10364         }
10365       }
10366       else {
10367         if(p!=chi[0]) return 0xfe;
10368         if (ch > 31) return 0xfe;
10369         map = (1L << ch);
10370       }
10371       if(chi[p] &0x40) return 0xfe;
10372     }
10373     if (pchannelmap) *pchannelmap = map;
10374     else if (map != ((dword)(1L << ch))) return 0xfe;
10375     return (byte)(excl | ch);
10376   }
10377   else {  /* not PRI */
10378     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10379     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10380     if(chi[1] &0x08) excl = 0x40;
10381
10382     switch(chi[1] |0x98) {
10383     case 0x98: return 0;
10384     case 0x99:
10385       if (pchannelmap) *pchannelmap = 2;
10386       return excl |1;
10387     case 0x9a:
10388       if (pchannelmap) *pchannelmap = 4;
10389       return excl |2;
10390     case 0x9b: return 0xff;
10391     case 0x9c: return 0xfd; /* d-ch */
10392     default: return 0xfe;
10393     }
10394   }
10395 }
10396
10397
10398 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10399 {
10400   DIVA_CAPI_ADAPTER   *a;
10401   PLCI   *splci;
10402   byte old_id;
10403
10404   a = plci->adapter;
10405   old_id = plci->li_bchannel_id;
10406   if (a->li_pri)
10407   {
10408     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10409       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10410     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10411     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10412       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10413   }
10414   else
10415   {
10416     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10417     {
10418       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10419         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10420       plci->li_bchannel_id = bchannel_id & 0x03;
10421       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10422       {
10423         splci = a->AdvSignalPLCI;
10424         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10425         {
10426           if ((splci->li_bchannel_id != 0)
10427            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10428           {
10429             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10430           }
10431           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10432           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10433           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10434             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10435             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10436         }
10437       }
10438       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10439         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10440     }
10441   }
10442   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10443    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10444   {
10445     mixer_clear_config (plci);
10446   }
10447   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10448     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10449     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10450 }
10451
10452
10453 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10454 {
10455   DIVA_CAPI_ADAPTER   *a;
10456   PLCI   *splci;
10457   byte ch, old_id;
10458
10459   a = plci->adapter;
10460   old_id = plci->li_bchannel_id;
10461   ch = chi_to_channel (chi, NULL);
10462   if (!(ch & 0x80))
10463   {
10464     if (a->li_pri)
10465     {
10466       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10467         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10468       plci->li_bchannel_id = (ch & 0x1f) + 1;
10469       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10470         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10471     }
10472     else
10473     {
10474       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10475       {
10476         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10477           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10478         plci->li_bchannel_id = ch & 0x1f;
10479         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10480         {
10481           splci = a->AdvSignalPLCI;
10482           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10483           {
10484             if ((splci->li_bchannel_id != 0)
10485              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10486             {
10487               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10488             }
10489             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10490             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10491             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10492               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10493               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10494           }
10495         }
10496         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10497           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10498       }
10499     }
10500   }
10501   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10502    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10503   {
10504     mixer_clear_config (plci);
10505   }
10506   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10507     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10508     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10509 }
10510
10511
10512 #define MIXER_MAX_DUMP_CHANNELS 34
10513
10514 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10515 {
10516 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10517   word n, i, j;
10518   char *p;
10519     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10520
10521   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10522     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10523
10524   for (i = 0; i < li_total_channels; i++)
10525   {
10526     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10527     if (li_config_table[i].chflags != 0)
10528       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10529     else
10530     {
10531       for (j = 0; j < li_total_channels; j++)
10532       {
10533         if (((li_config_table[i].flag_table[j]) != 0)
10534          || ((li_config_table[j].flag_table[i]) != 0))
10535         {
10536           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10537         }
10538         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10539          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10540         {
10541           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10542         }
10543       }
10544     }
10545   }
10546   for (i = 0; i < li_total_channels; i++)
10547   {
10548     for (j = 0; j < li_total_channels; j++)
10549     {
10550       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10551       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10552         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10553     }
10554   }
10555   for (n = 0; n < li_total_channels; n++)
10556   {
10557     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10558     {
10559       for (i = 0; i < li_total_channels; i++)
10560       {
10561         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10562         {
10563           for (j = 0; j < li_total_channels; j++)
10564           {
10565             li_config_table[i].coef_table[j] |=
10566               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10567           }
10568         }
10569       }
10570     }
10571   }
10572   for (i = 0; i < li_total_channels; i++)
10573   {
10574     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10575     {
10576       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10577       for (j = 0; j < li_total_channels; j++)
10578       {
10579         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10580           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10581       }
10582       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10583         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10584     }
10585   }
10586   for (i = 0; i < li_total_channels; i++)
10587   {
10588     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10589     {
10590       for (j = 0; j < li_total_channels; j++)
10591       {
10592         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10593           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10594         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10595           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10596         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10597           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10598         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10599           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10600       }
10601       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10602       {
10603         for (j = 0; j < li_total_channels; j++)
10604         {
10605           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10606           {
10607             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10608             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10609               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10610           }
10611         }
10612       }
10613       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10614       {
10615         for (j = 0; j < li_total_channels; j++)
10616         {
10617           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10618             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10619         }
10620       }
10621       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10622       {
10623         for (j = 0; j < li_total_channels; j++)
10624         {
10625           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10626           {
10627             for (n = 0; n < li_total_channels; n++)
10628             {
10629               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10630               {
10631                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10632                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10633                 {
10634                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10635                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10636                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10637                 }
10638                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10639                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10640               }
10641             }
10642           }
10643         }
10644       }
10645     }
10646   }
10647   for (i = 0; i < li_total_channels; i++)
10648   {
10649     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10650     {
10651       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10652         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10653       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10654         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10655       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10656         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10657       for (j = 0; j < li_total_channels; j++)
10658       {
10659         if ((li_config_table[i].flag_table[j] &
10660           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10661          || (li_config_table[j].flag_table[i] &
10662           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10663         {
10664           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10665         }
10666         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10667           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10668         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10669           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10670       }
10671       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10672       {
10673         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10674         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10675       }
10676     }
10677   }
10678   for (i = 0; i < li_total_channels; i++)
10679   {
10680     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10681     {
10682       j = 0;
10683       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10684         j++;
10685       if (j < li_total_channels)
10686       {
10687         for (j = 0; j < li_total_channels; j++)
10688         {
10689           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10690           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10691             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10692         }
10693       }
10694     }
10695   }
10696   n = li_total_channels;
10697   if (n > MIXER_MAX_DUMP_CHANNELS)
10698     n = MIXER_MAX_DUMP_CHANNELS;
10699   p = hex_line;
10700   for (j = 0; j < n; j++)
10701   {
10702     if ((j & 0x7) == 0)
10703       *(p++) = ' ';
10704     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10705     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10706   }
10707   *p = '\0';
10708   dbug (1, dprintf ("[%06lx] CURRENT %s",
10709     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10710   p = hex_line;
10711   for (j = 0; j < n; j++)
10712   {
10713     if ((j & 0x7) == 0)
10714       *(p++) = ' ';
10715     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10716     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10717   }
10718   *p = '\0';
10719   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10720     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10721   p = hex_line;
10722   for (j = 0; j < n; j++)
10723   {
10724     if ((j & 0x7) == 0)
10725       *(p++) = ' ';
10726     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10727     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10728   }
10729   *p = '\0';
10730   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10731     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10732   for (i = 0; i < n; i++)
10733   {
10734     p = hex_line;
10735     for (j = 0; j < n; j++)
10736     {
10737       if ((j & 0x7) == 0)
10738         *(p++) = ' ';
10739       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10740       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10741     }
10742     *p = '\0';
10743     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10744       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10745   }
10746   for (i = 0; i < n; i++)
10747   {
10748     p = hex_line;
10749     for (j = 0; j < n; j++)
10750     {
10751       if ((j & 0x7) == 0)
10752         *(p++) = ' ';
10753       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10754       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10755     }
10756     *p = '\0';
10757     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10758       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10759   }
10760 }
10761
10762
10763 static struct
10764 {
10765   byte mask;
10766   byte line_flags;
10767 } mixer_write_prog_pri[] =
10768 {
10769   { LI_COEF_CH_CH, 0 },
10770   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10771   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10772   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10773 };
10774
10775 static struct
10776 {
10777   byte from_ch;
10778   byte to_ch;
10779   byte mask;
10780   byte xconnect_override;
10781 } mixer_write_prog_bri[] =
10782 {
10783   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10784   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10785   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10786   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10787   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10788   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10789   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10790   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10791   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10792   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10793   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10794   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10795   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10796   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10797   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10798   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10799   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10800   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10801   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10802   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10803   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10804   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10805   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10806   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10807   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10808   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10809   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10810   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10811   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10812   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10813   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10814   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10815   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10816   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10817   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10818   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10819 };
10820
10821 static byte mixer_swapped_index_bri[] =
10822 {
10823   18,  /* B      to B      */
10824   19,  /* Alt B  to B      */
10825   20,  /* PC     to B      */
10826   21,  /* Alt PC to B      */
10827   22,  /* IC     to B      */
10828   23,  /* Alt IC to B      */
10829   24,  /* B      to PC     */
10830   25,  /* Alt B  to PC     */
10831   26,  /* PC     to PC     */
10832   27,  /* Alt PC to PC     */
10833   28,  /* IC     to PC     */
10834   29,  /* Alt IC to PC     */
10835   30,  /* B      to IC     */
10836   31,  /* Alt B  to IC     */
10837   32,  /* PC     to IC     */
10838   33,  /* Alt PC to IC     */
10839   34,  /* IC     to IC     */
10840   35,  /* Alt IC to IC     */
10841   0,   /* Alt B  to Alt B  */
10842   1,   /* B      to Alt B  */
10843   2,   /* Alt PC to Alt B  */
10844   3,   /* PC     to Alt B  */
10845   4,   /* Alt IC to Alt B  */
10846   5,   /* IC     to Alt B  */
10847   6,   /* Alt B  to Alt PC */
10848   7,   /* B      to Alt PC */
10849   8,   /* Alt PC to Alt PC */
10850   9,   /* PC     to Alt PC */
10851   10,  /* Alt IC to Alt PC */
10852   11,  /* IC     to Alt PC */
10853   12,  /* Alt B  to Alt IC */
10854   13,  /* B      to Alt IC */
10855   14,  /* Alt PC to Alt IC */
10856   15,  /* PC     to Alt IC */
10857   16,  /* Alt IC to Alt IC */
10858   17   /* IC     to Alt IC */
10859 };
10860
10861 static struct
10862 {
10863   byte mask;
10864   byte from_pc;
10865   byte to_pc;
10866 } xconnect_write_prog[] =
10867 {
10868   { LI_COEF_CH_CH, false, false },
10869   { LI_COEF_CH_PC, false, true },
10870   { LI_COEF_PC_CH, true, false },
10871   { LI_COEF_PC_PC, true, true }
10872 };
10873
10874
10875 static void xconnect_query_addresses (PLCI   *plci)
10876 {
10877   DIVA_CAPI_ADAPTER   *a;
10878   word w, ch;
10879   byte   *p;
10880
10881   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10882     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10883     (char   *)(FILE_), __LINE__));
10884
10885   a = plci->adapter;
10886   if (a->li_pri && ((plci->li_bchannel_id == 0)
10887    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10888   {
10889     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10890       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10891       (char   *)(FILE_), __LINE__));
10892     return;
10893   }
10894   p = plci->internal_req_buffer;
10895   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10896   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10897   w = ch;
10898   *(p++) = (byte) w;
10899   *(p++) = (byte)(w >> 8);
10900   w = ch | XCONNECT_CHANNEL_PORT_PC;
10901   *(p++) = (byte) w;
10902   *(p++) = (byte)(w >> 8);
10903   plci->NData[0].P = plci->internal_req_buffer;
10904   plci->NData[0].PLength = p - plci->internal_req_buffer;
10905   plci->NL.X = plci->NData;
10906   plci->NL.ReqCh = 0;
10907   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10908   plci->adapter->request (&plci->NL);
10909 }
10910
10911
10912 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10913 {
10914
10915   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10916     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10917     (char   *)(FILE_), __LINE__, internal_command));
10918
10919   plci->li_write_command = internal_command;
10920   plci->li_write_channel = 0;
10921 }
10922
10923
10924 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10925 {
10926   DIVA_CAPI_ADAPTER   *a;
10927   word w, n, i, j, r, s, to_ch;
10928   dword d;
10929   byte   *p;
10930   struct xconnect_transfer_address_s   *transfer_address;
10931   byte ch_map[MIXER_CHANNELS_BRI];
10932
10933   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10934     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10935
10936   a = plci->adapter;
10937   if ((plci->li_bchannel_id == 0)
10938    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10939   {
10940     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10941       UnMapId (Id), (char   *)(FILE_), __LINE__));
10942     return (true);
10943   }
10944   i = a->li_base + (plci->li_bchannel_id - 1);
10945   j = plci->li_write_channel;
10946   p = plci->internal_req_buffer;
10947   if (j != 0)
10948   {
10949     if ((Rc != OK) && (Rc != OK_FC))
10950     {
10951       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10952         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10953       return (false);
10954     }
10955   }
10956   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10957   {
10958     r = 0;
10959     s = 0;
10960     if (j < li_total_channels)
10961     {
10962       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10963       {
10964         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10965             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10966           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10967             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10968       }
10969       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10970       while ((j < li_total_channels)
10971         && ((r == 0)
10972          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10973          || (!li_config_table[j].adapter->li_pri
10974           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10975          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10976            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10977           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10978            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10979          || ((li_config_table[j].adapter->li_base != a->li_base)
10980           && !(r & s &
10981             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10982               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10983             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10984               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10985       {
10986         j++;
10987         if (j < li_total_channels)
10988           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10989       }
10990     }
10991     if (j < li_total_channels)
10992     {
10993       plci->internal_command = plci->li_write_command;
10994       if (plci_nl_busy (plci))
10995         return (true);
10996       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10997       *(p++) = UDATA_REQUEST_XCONNECT_TO;
10998       do
10999       {
11000         if (li_config_table[j].adapter->li_base != a->li_base)
11001         {
11002           r &= s &
11003             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11004               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11005             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11006               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11007         }
11008         n = 0;
11009         do
11010         {
11011           if (r & xconnect_write_prog[n].mask)
11012           {
11013             if (xconnect_write_prog[n].from_pc)
11014               transfer_address = &(li_config_table[j].send_pc);
11015             else
11016               transfer_address = &(li_config_table[j].send_b);
11017             d = transfer_address->card_address.low;
11018             *(p++) = (byte) d;
11019             *(p++) = (byte)(d >> 8);
11020             *(p++) = (byte)(d >> 16);
11021             *(p++) = (byte)(d >> 24);
11022             d = transfer_address->card_address.high;
11023             *(p++) = (byte) d;
11024             *(p++) = (byte)(d >> 8);
11025             *(p++) = (byte)(d >> 16);
11026             *(p++) = (byte)(d >> 24);
11027             d = transfer_address->offset;
11028             *(p++) = (byte) d;
11029             *(p++) = (byte)(d >> 8);
11030             *(p++) = (byte)(d >> 16);
11031             *(p++) = (byte)(d >> 24);
11032             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11033             *(p++) = (byte) w;
11034             *(p++) = (byte)(w >> 8);
11035             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11036               (li_config_table[i].adapter->u_law ?
11037                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11038                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11039             *(p++) = (byte) w;
11040             *(p++) = (byte) 0;
11041             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11042           }
11043           n++;
11044         } while ((n < ARRAY_SIZE(xconnect_write_prog))
11045           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11046         if (n == ARRAY_SIZE(xconnect_write_prog))
11047         {
11048           do
11049           {
11050             j++;
11051             if (j < li_total_channels)
11052               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11053           } while ((j < li_total_channels)
11054             && ((r == 0)
11055              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11056              || (!li_config_table[j].adapter->li_pri
11057               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11058              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11059                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11060               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11061                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11062              || ((li_config_table[j].adapter->li_base != a->li_base)
11063               && !(r & s &
11064                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11065                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11066                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11067                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11068         }
11069       } while ((j < li_total_channels)
11070         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11071     }
11072     else if (j == li_total_channels)
11073     {
11074       plci->internal_command = plci->li_write_command;
11075       if (plci_nl_busy (plci))
11076         return (true);
11077       if (a->li_pri)
11078       {
11079         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11080         w = 0;
11081         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11082           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11083         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11084           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11085         *(p++) = (byte) w;
11086         *(p++) = (byte)(w >> 8);
11087       }
11088       else
11089       {
11090         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11091         w = 0;
11092         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11093          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11094         {
11095           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11096         }
11097         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11098           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11099         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11100           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11101         *(p++) = (byte) w;
11102         *(p++) = (byte)(w >> 8);
11103         for (j = 0; j < sizeof(ch_map); j += 2)
11104         {
11105           if (plci->li_bchannel_id == 2)
11106           {
11107             ch_map[j] = (byte)(j+1);
11108             ch_map[j+1] = (byte) j;
11109           }
11110           else
11111           {
11112             ch_map[j] = (byte) j;
11113             ch_map[j+1] = (byte)(j+1);
11114           }
11115         }
11116         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11117         {
11118           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11119           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11120           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11121           {
11122             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11123               mixer_write_prog_bri[n].xconnect_override :
11124               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11125             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11126             {
11127               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11128               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11129             }
11130           }
11131           else
11132           {
11133             *p = 0x00;
11134             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11135             {
11136               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11137               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11138                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11139             }
11140           }
11141           p++;
11142         }
11143       }
11144       j = li_total_channels + 1;
11145     }
11146   }
11147   else
11148   {
11149     if (j <= li_total_channels)
11150     {
11151       plci->internal_command = plci->li_write_command;
11152       if (plci_nl_busy (plci))
11153         return (true);
11154       if (j < a->li_base)
11155         j = a->li_base;
11156       if (a->li_pri)
11157       {
11158         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11159         w = 0;
11160         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11161           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11162         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11163           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11164         *(p++) = (byte) w;
11165         *(p++) = (byte)(w >> 8);
11166         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11167         {
11168           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11169           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11170           {
11171             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11172             if (w & mixer_write_prog_pri[n].mask)
11173             {
11174               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11175               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11176             }
11177             else
11178               *(p++) = 0x00;
11179           }
11180           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11181           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11182           {
11183             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11184             if (w & mixer_write_prog_pri[n].mask)
11185             {
11186               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11187               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11188             }
11189             else
11190               *(p++) = 0x00;
11191           }
11192         }
11193       }
11194       else
11195       {
11196         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11197         w = 0;
11198         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11199          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11200         {
11201           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11202         }
11203         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11204           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11205         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11206           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11207         *(p++) = (byte) w;
11208         *(p++) = (byte)(w >> 8);
11209         for (j = 0; j < sizeof(ch_map); j += 2)
11210         {
11211           if (plci->li_bchannel_id == 2)
11212           {
11213             ch_map[j] = (byte)(j+1);
11214             ch_map[j+1] = (byte) j;
11215           }
11216           else
11217           {
11218             ch_map[j] = (byte) j;
11219             ch_map[j+1] = (byte)(j+1);
11220           }
11221         }
11222         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11223         {
11224           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11225           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11226           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11227           {
11228             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11229             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11230             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11231           }
11232           else
11233           {
11234             *p = 0x00;
11235             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11236             {
11237               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11238               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11239                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11240             }
11241           }
11242           p++;
11243         }
11244       }
11245       j = li_total_channels + 1;
11246     }
11247   }
11248   plci->li_write_channel = j;
11249   if (p != plci->internal_req_buffer)
11250   {
11251     plci->NData[0].P = plci->internal_req_buffer;
11252     plci->NData[0].PLength = p - plci->internal_req_buffer;
11253     plci->NL.X = plci->NData;
11254     plci->NL.ReqCh = 0;
11255     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11256     plci->adapter->request (&plci->NL);
11257   }
11258   return (true);
11259 }
11260
11261
11262 static void mixer_notify_update (PLCI   *plci, byte others)
11263 {
11264   DIVA_CAPI_ADAPTER   *a;
11265   word i, w;
11266   PLCI   *notify_plci;
11267     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11268
11269   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11270     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11271     (char   *)(FILE_), __LINE__, others));
11272
11273   a = plci->adapter;
11274   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11275   {
11276     if (others)
11277       plci->li_notify_update = true;
11278     i = 0;
11279     do
11280     {
11281       notify_plci = NULL;
11282       if (others)
11283       {
11284         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11285           i++;
11286         if (i < li_total_channels)
11287           notify_plci = li_config_table[i++].plci;
11288       }
11289       else
11290       {
11291         if ((plci->li_bchannel_id != 0)
11292          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11293         {
11294           notify_plci = plci;
11295         }
11296       }
11297       if ((notify_plci != NULL)
11298        && !notify_plci->li_notify_update
11299        && (notify_plci->appl != NULL)
11300        && (notify_plci->State)
11301        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11302       {
11303         notify_plci->li_notify_update = true;
11304         ((CAPI_MSG *) msg)->header.length = 18;
11305         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11306         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11307         ((CAPI_MSG *) msg)->header.number = 0;
11308         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11309         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11310         ((CAPI_MSG *) msg)->header.ncci = 0;
11311         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11312         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11313         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11314         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11315         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11316         if (w != _QUEUE_FULL)
11317         {
11318           if (w != 0)
11319           {
11320             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11321               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11322               (char   *)(FILE_), __LINE__,
11323               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11324           }
11325           notify_plci->li_notify_update = false;
11326         }
11327       }
11328     } while (others && (notify_plci != NULL));
11329     if (others)
11330       plci->li_notify_update = false;
11331   }
11332 }
11333
11334
11335 static void mixer_clear_config (PLCI   *plci)
11336 {
11337   DIVA_CAPI_ADAPTER   *a;
11338   word i, j;
11339
11340   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11341     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11342     (char   *)(FILE_), __LINE__));
11343
11344   plci->li_notify_update = false;
11345   plci->li_plci_b_write_pos = 0;
11346   plci->li_plci_b_read_pos = 0;
11347   plci->li_plci_b_req_pos = 0;
11348   a = plci->adapter;
11349   if ((plci->li_bchannel_id != 0)
11350    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11351   {
11352     i = a->li_base + (plci->li_bchannel_id - 1);
11353     li_config_table[i].curchnl = 0;
11354     li_config_table[i].channel = 0;
11355     li_config_table[i].chflags = 0;
11356     for (j = 0; j < li_total_channels; j++)
11357     {
11358       li_config_table[j].flag_table[i] = 0;
11359       li_config_table[i].flag_table[j] = 0;
11360       li_config_table[i].coef_table[j] = 0;
11361       li_config_table[j].coef_table[i] = 0;
11362     }
11363     if (!a->li_pri)
11364     {
11365       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11366       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11367       {
11368         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11369         li_config_table[i].curchnl = 0;
11370         li_config_table[i].channel = 0;
11371         li_config_table[i].chflags = 0;
11372         for (j = 0; j < li_total_channels; j++)
11373         {
11374           li_config_table[i].flag_table[j] = 0;
11375           li_config_table[j].flag_table[i] = 0;
11376           li_config_table[i].coef_table[j] = 0;
11377           li_config_table[j].coef_table[i] = 0;
11378         }
11379         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11380         {
11381           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11382           li_config_table[i].curchnl = 0;
11383           li_config_table[i].channel = 0;
11384           li_config_table[i].chflags = 0;
11385           for (j = 0; j < li_total_channels; j++)
11386           {
11387             li_config_table[i].flag_table[j] = 0;
11388             li_config_table[j].flag_table[i] = 0;
11389             li_config_table[i].coef_table[j] = 0;
11390             li_config_table[j].coef_table[i] = 0;
11391           }
11392         }
11393       }
11394     }
11395   }
11396 }
11397
11398
11399 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11400 {
11401
11402   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11403     UnMapId (Id), (char   *)(FILE_), __LINE__));
11404
11405   do
11406   {
11407     mixer_indication_coefs_set (Id, plci);
11408   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11409 }
11410
11411
11412 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11413 {
11414   DIVA_CAPI_ADAPTER   *a;
11415   word i, j;
11416
11417   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11418     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11419
11420   a = plci->adapter;
11421   if ((plci->li_bchannel_id != 0)
11422    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11423   {
11424     i = a->li_base + (plci->li_bchannel_id - 1);
11425     for (j = 0; j < li_total_channels; j++)
11426     {
11427       li_config_table[i].coef_table[j] &= 0xf;
11428       li_config_table[j].coef_table[i] &= 0xf;
11429     }
11430     if (!a->li_pri)
11431       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11432   }
11433   return (GOOD);
11434 }
11435
11436
11437 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11438 {
11439   DIVA_CAPI_ADAPTER   *a;
11440   word Info;
11441
11442   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11443     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11444
11445   Info = GOOD;
11446   a = plci->adapter;
11447   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11448    && (plci->li_bchannel_id != 0)
11449    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11450   {
11451     switch (plci->adjust_b_state)
11452     {
11453     case ADJUST_B_RESTORE_MIXER_1:
11454       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11455       {
11456         plci->internal_command = plci->adjust_b_command;
11457         if (plci_nl_busy (plci))
11458         {
11459           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11460           break;
11461         }
11462         xconnect_query_addresses (plci);
11463         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11464         break;
11465       }
11466       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11467       Rc = OK;
11468     case ADJUST_B_RESTORE_MIXER_2:
11469     case ADJUST_B_RESTORE_MIXER_3:
11470     case ADJUST_B_RESTORE_MIXER_4:
11471       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11472       {
11473         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11474           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11475         Info = _WRONG_STATE;
11476         break;
11477       }
11478       if (Rc == OK)
11479       {
11480         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11481           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11482         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11483           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11484       }
11485       else if (Rc == 0)
11486       {
11487         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11488           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11489         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11490           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11491       }
11492       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11493       {
11494         plci->internal_command = plci->adjust_b_command;
11495         break;
11496       }
11497     case ADJUST_B_RESTORE_MIXER_5:
11498       xconnect_write_coefs (plci, plci->adjust_b_command);
11499       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11500       Rc = OK;
11501     case ADJUST_B_RESTORE_MIXER_6:
11502       if (!xconnect_write_coefs_process (Id, plci, Rc))
11503       {
11504         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11505           UnMapId (Id), (char   *)(FILE_), __LINE__));
11506         Info = _FACILITY_NOT_SUPPORTED;
11507         break;
11508       }
11509       if (plci->internal_command)
11510         break;
11511       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11512     case ADJUST_B_RESTORE_MIXER_7:
11513       break;
11514     }
11515   }
11516   return (Info);
11517 }
11518
11519
11520 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11521 {
11522   DIVA_CAPI_ADAPTER   *a;
11523   word i, internal_command, Info;
11524
11525   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11526     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11527     plci->li_cmd));
11528
11529   Info = GOOD;
11530   a = plci->adapter;
11531   internal_command = plci->internal_command;
11532   plci->internal_command = 0;
11533   switch (plci->li_cmd)
11534   {
11535   case LI_REQ_CONNECT:
11536   case LI_REQ_DISCONNECT:
11537   case LI_REQ_SILENT_UPDATE:
11538     switch (internal_command)
11539     {
11540     default:
11541       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11542       {
11543         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11544           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11545       }
11546     case MIXER_COMMAND_1:
11547       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11548       {
11549         if (adjust_b_process (Id, plci, Rc) != GOOD)
11550         {
11551           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11552             UnMapId (Id), (char   *)(FILE_), __LINE__));
11553           Info = _FACILITY_NOT_SUPPORTED;
11554           break;
11555         }
11556         if (plci->internal_command)
11557           return;
11558       }
11559       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11560       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11561        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11562         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11563          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11564       {
11565         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11566       }
11567       else
11568       {
11569         do
11570         {
11571           mixer_indication_coefs_set (Id, plci);
11572         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11573       }
11574     case MIXER_COMMAND_2:
11575       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11576        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11577         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11578          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11579       {
11580         if (!xconnect_write_coefs_process (Id, plci, Rc))
11581         {
11582           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11583             UnMapId (Id), (char   *)(FILE_), __LINE__));
11584           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11585           {
11586             do
11587             {
11588               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11589                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11590               i = (plci->li_plci_b_write_pos == 0) ?
11591                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11592             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11593               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11594           }
11595           Info = _FACILITY_NOT_SUPPORTED;
11596           break;
11597         }
11598         if (plci->internal_command)
11599           return;
11600       }
11601       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11602       {
11603         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11604           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11605       }
11606     case MIXER_COMMAND_3:
11607       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11608       {
11609         if (adjust_b_process (Id, plci, Rc) != GOOD)
11610         {
11611           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11612             UnMapId (Id), (char   *)(FILE_), __LINE__));
11613           Info = _FACILITY_NOT_SUPPORTED;
11614           break;
11615         }
11616         if (plci->internal_command)
11617           return;
11618       }
11619       break;
11620     }
11621     break;
11622   }
11623   if ((plci->li_bchannel_id == 0)
11624    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11625   {
11626     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11627       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11628   }
11629   else
11630   {
11631     i = a->li_base + (plci->li_bchannel_id - 1);
11632     li_config_table[i].curchnl = plci->li_channel_bits;
11633     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11634     {
11635       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11636       li_config_table[i].curchnl = plci->li_channel_bits;
11637       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11638       {
11639         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11640         li_config_table[i].curchnl = plci->li_channel_bits;
11641       }
11642     }
11643   }
11644 }
11645
11646
11647 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11648   dword plci_b_id, byte connect, dword li_flags)
11649 {
11650   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11651   PLCI   *plci_b;
11652   DIVA_CAPI_ADAPTER   *a_b;
11653
11654   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11655   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11656   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11657   if (!a->li_pri && (plci->tel == ADV_VOICE)
11658    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11659   {
11660     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11661     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11662       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11663   }
11664   else
11665   {
11666     ch_a_v = ch_a;
11667     ch_a_s = ch_a;
11668   }
11669   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11670   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11671    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11672   {
11673     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11674     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11675       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11676   }
11677   else
11678   {
11679     ch_b_v = ch_b;
11680     ch_b_s = ch_b;
11681   }
11682   if (connect)
11683   {
11684     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11685     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11686     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11687     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11688   }
11689   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11690   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11691   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11692   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11693   if (ch_a_v == ch_b_v)
11694   {
11695     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11696     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11697   }
11698   else
11699   {
11700     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11701     {
11702       for (i = 0; i < li_total_channels; i++)
11703       {
11704         if (i != ch_a_v)
11705           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11706       }
11707     }
11708     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11709     {
11710       for (i = 0; i < li_total_channels; i++)
11711       {
11712         if (i != ch_a_s)
11713           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11714       }
11715     }
11716     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11717     {
11718       for (i = 0; i < li_total_channels; i++)
11719       {
11720         if (i != ch_a_v)
11721           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11722       }
11723     }
11724     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11725     {
11726       for (i = 0; i < li_total_channels; i++)
11727       {
11728         if (i != ch_a_s)
11729           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11730       }
11731     }
11732   }
11733   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11734   {
11735     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11736     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11737     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11738     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11739   }
11740   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11741   {
11742     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11743     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11744     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11745     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11746   }
11747   if (li_flags & LI_FLAG_MONITOR_A)
11748   {
11749     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11750     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11751   }
11752   if (li_flags & LI_FLAG_MONITOR_B)
11753   {
11754     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11755     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11756   }
11757   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11758   {
11759     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11760     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11761   }
11762   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11763   {
11764     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11765     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11766   }
11767   if (li_flags & LI_FLAG_MIX_A)
11768   {
11769     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11770     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11771   }
11772   if (li_flags & LI_FLAG_MIX_B)
11773   {
11774     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11775     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11776   }
11777   if (ch_a_v != ch_a_s)
11778   {
11779     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11780     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11781   }
11782   if (ch_b_v != ch_b_s)
11783   {
11784     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11785     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11786   }
11787 }
11788
11789
11790 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11791   dword plci_b_id, byte connect, dword li_flags)
11792 {
11793   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11794   PLCI   *plci_b;
11795   DIVA_CAPI_ADAPTER   *a_b;
11796
11797   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11798   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11799   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11800   if (!a->li_pri && (plci->tel == ADV_VOICE)
11801    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11802   {
11803     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11804     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11805       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11806   }
11807   else
11808   {
11809     ch_a_v = ch_a;
11810     ch_a_s = ch_a;
11811   }
11812   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11813   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11814    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11815   {
11816     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11817     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11818       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11819   }
11820   else
11821   {
11822     ch_b_v = ch_b;
11823     ch_b_s = ch_b;
11824   }
11825   if (connect)
11826   {
11827     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11828     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11829     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11830     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11831     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11832     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11833   }
11834   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11835   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11836   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11837   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11838   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11839   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11840   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11841   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11842   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11843   {
11844     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11845     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11846     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11847     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11848   }
11849   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11850   {
11851     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11852     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11853     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11854     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11855   }
11856   if (li_flags & LI2_FLAG_MONITOR_B)
11857   {
11858     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11859     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11860   }
11861   if (li_flags & LI2_FLAG_MIX_B)
11862   {
11863     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11864     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11865   }
11866   if (li_flags & LI2_FLAG_MONITOR_X)
11867     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11868   if (li_flags & LI2_FLAG_MIX_X)
11869     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11870   if (li_flags & LI2_FLAG_LOOP_B)
11871   {
11872     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11873     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11874     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11875     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11876   }
11877   if (li_flags & LI2_FLAG_LOOP_PC)
11878     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11879   if (li_flags & LI2_FLAG_LOOP_X)
11880     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11881   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11882     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11883   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11884     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11885   if (ch_a_v != ch_a_s)
11886   {
11887     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11888     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11889   }
11890   if (ch_b_v != ch_b_s)
11891   {
11892     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11893     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11894   }
11895 }
11896
11897
11898 static word li_check_main_plci (dword Id, PLCI   *plci)
11899 {
11900   if (plci == NULL)
11901   {
11902     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11903       UnMapId (Id), (char   *)(FILE_), __LINE__));
11904     return (_WRONG_IDENTIFIER);
11905   }
11906   if (!plci->State
11907    || !plci->NL.Id || plci->nl_remove_id
11908    || (plci->li_bchannel_id == 0))
11909   {
11910     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11911       UnMapId (Id), (char   *)(FILE_), __LINE__));
11912     return (_WRONG_STATE);
11913   }
11914   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11915   return (GOOD);
11916 }
11917
11918
11919 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11920   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11921 {
11922   byte ctlr_b;
11923   PLCI   *plci_b;
11924
11925   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11926     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11927   {
11928     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11929       UnMapId (Id), (char   *)(FILE_), __LINE__));
11930     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11931     return (NULL);
11932   }
11933   ctlr_b = 0;
11934   if ((plci_b_id & 0x7f) != 0)
11935   {
11936     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11937     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11938       ctlr_b = 0;
11939   }
11940   if ((ctlr_b == 0)
11941    || (((plci_b_id >> 8) & 0xff) == 0)
11942    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11943   {
11944     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11945       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11946     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11947     return (NULL);
11948   }
11949   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11950   if (!plci_b->State
11951    || !plci_b->NL.Id || plci_b->nl_remove_id
11952    || (plci_b->li_bchannel_id == 0))
11953   {
11954     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11955       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11956     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11957     return (NULL);
11958   }
11959   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11960   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11961     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11962    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11963     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11964   {
11965     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11966       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11967     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11968     return (NULL);
11969   }
11970   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11971     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11972   {
11973     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11974       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11975     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11976     return (NULL);
11977   }
11978   return (plci_b);
11979 }
11980
11981
11982 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11983   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11984 {
11985   byte ctlr_b;
11986   PLCI   *plci_b;
11987
11988   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11989     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11990   {
11991     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11992       UnMapId (Id), (char   *)(FILE_), __LINE__));
11993     PUT_WORD (p_result, _WRONG_STATE);
11994     return (NULL);
11995   }
11996   ctlr_b = 0;
11997   if ((plci_b_id & 0x7f) != 0)
11998   {
11999     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
12000     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
12001       ctlr_b = 0;
12002   }
12003   if ((ctlr_b == 0)
12004    || (((plci_b_id >> 8) & 0xff) == 0)
12005    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
12006   {
12007     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
12008       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12009     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12010     return (NULL);
12011   }
12012   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12013   if (!plci_b->State
12014    || !plci_b->NL.Id || plci_b->nl_remove_id
12015    || (plci_b->li_bchannel_id == 0)
12016    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12017   {
12018     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12019       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12020     PUT_WORD (p_result, _WRONG_STATE);
12021     return (NULL);
12022   }
12023   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12024     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12025    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12026     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12027   {
12028     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12029       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12030     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12031     return (NULL);
12032   }
12033   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12034     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12035   {
12036     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12037       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12038     PUT_WORD (p_result, _WRONG_STATE);
12039     return (NULL);
12040   }
12041   return (plci_b);
12042 }
12043
12044
12045 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12046 {
12047   word Info;
12048   word i;
12049   dword d, li_flags, plci_b_id;
12050   PLCI   *plci_b;
12051     API_PARSE li_parms[3];
12052     API_PARSE li_req_parms[3];
12053     API_PARSE li_participant_struct[2];
12054     API_PARSE li_participant_parms[3];
12055   word participant_parms_pos;
12056   byte result_buffer[32];
12057   byte   *result;
12058   word result_pos;
12059   word plci_b_write_pos;
12060
12061   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12062     UnMapId (Id), (char   *)(FILE_), __LINE__));
12063
12064   Info = GOOD;
12065   result = result_buffer;
12066   result_buffer[0] = 0;
12067   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12068   {
12069     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12070       UnMapId (Id), (char   *)(FILE_), __LINE__));
12071     Info = _FACILITY_NOT_SUPPORTED;
12072   }
12073   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12074   {
12075     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12076       UnMapId (Id), (char   *)(FILE_), __LINE__));
12077     Info = _WRONG_MESSAGE_FORMAT;
12078   }
12079   else
12080   {
12081     result_buffer[0] = 3;
12082     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12083     result_buffer[3] = 0;
12084     switch (GET_WORD (li_parms[0].info))
12085     {
12086     case LI_GET_SUPPORTED_SERVICES:
12087       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12088       {
12089         result_buffer[0] = 17;
12090         result_buffer[3] = 14;
12091         PUT_WORD (&result_buffer[4], GOOD);
12092         d = 0;
12093         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12094           d |= LI_CONFERENCING_SUPPORTED;
12095         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12096           d |= LI_MONITORING_SUPPORTED;
12097         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12098           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12099         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12100           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12101         PUT_DWORD (&result_buffer[6], d);
12102         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12103         {
12104           d = 0;
12105           for (i = 0; i < li_total_channels; i++)
12106           {
12107             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12108              && (li_config_table[i].adapter->li_pri
12109               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12110             {
12111               d++;
12112             }
12113           }
12114         }
12115         else
12116         {
12117           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12118         }
12119         PUT_DWORD (&result_buffer[10], d / 2);
12120         PUT_DWORD (&result_buffer[14], d);
12121       }
12122       else
12123       {
12124         result_buffer[0] = 25;
12125         result_buffer[3] = 22;
12126         PUT_WORD (&result_buffer[4], GOOD);
12127         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12128         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12129           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12130         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12131           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12132         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12133           d |= LI2_PC_LOOPING_SUPPORTED;
12134         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12135           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12136         PUT_DWORD (&result_buffer[6], d);
12137         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12138         PUT_DWORD (&result_buffer[10], d / 2);
12139         PUT_DWORD (&result_buffer[14], d - 1);
12140         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12141         {
12142           d = 0;
12143           for (i = 0; i < li_total_channels; i++)
12144           {
12145             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12146              && (li_config_table[i].adapter->li_pri
12147               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12148             {
12149               d++;
12150             }
12151           }
12152         }
12153         PUT_DWORD (&result_buffer[18], d / 2);
12154         PUT_DWORD (&result_buffer[22], d - 1);
12155       }
12156       break;
12157
12158     case LI_REQ_CONNECT:
12159       if (li_parms[1].length == 8)
12160       {
12161         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12162         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12163         {
12164           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12165             UnMapId (Id), (char   *)(FILE_), __LINE__));
12166           Info = _WRONG_MESSAGE_FORMAT;
12167           break;
12168         }
12169         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12170         li_flags = GET_DWORD (li_req_parms[1].info);
12171         Info = li_check_main_plci (Id, plci);
12172         result_buffer[0] = 9;
12173         result_buffer[3] = 6;
12174         PUT_DWORD (&result_buffer[4], plci_b_id);
12175         PUT_WORD (&result_buffer[8], GOOD);
12176         if (Info != GOOD)
12177           break;
12178         result = plci->saved_msg.info;
12179         for (i = 0; i <= result_buffer[0]; i++)
12180           result[i] = result_buffer[i];
12181         plci_b_write_pos = plci->li_plci_b_write_pos;
12182         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12183         if (plci_b == NULL)
12184           break;
12185         li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12186         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12187         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12188         plci->li_plci_b_write_pos = plci_b_write_pos;
12189       }
12190       else
12191       {
12192         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12193         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12194         {
12195           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12196             UnMapId (Id), (char   *)(FILE_), __LINE__));
12197           Info = _WRONG_MESSAGE_FORMAT;
12198           break;
12199         }
12200         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12201         Info = li_check_main_plci (Id, plci);
12202         result_buffer[0] = 7;
12203         result_buffer[3] = 4;
12204         PUT_WORD (&result_buffer[4], Info);
12205         result_buffer[6] = 0;
12206         if (Info != GOOD)
12207           break;
12208         result = plci->saved_msg.info;
12209         for (i = 0; i <= result_buffer[0]; i++)
12210           result[i] = result_buffer[i];
12211         plci_b_write_pos = plci->li_plci_b_write_pos;
12212         participant_parms_pos = 0;
12213         result_pos = 7;
12214         li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12215         while (participant_parms_pos < li_req_parms[1].length)
12216         {
12217           result[result_pos] = 6;
12218           result_pos += 7;
12219           PUT_DWORD (&result[result_pos - 6], 0);
12220           PUT_WORD (&result[result_pos - 2], GOOD);
12221           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12222             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12223           {
12224             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12225               UnMapId (Id), (char   *)(FILE_), __LINE__));
12226             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12227             break;
12228           }
12229           if (api_parse (&li_participant_struct[0].info[1],
12230             li_participant_struct[0].length, "dd", li_participant_parms))
12231           {
12232             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12233               UnMapId (Id), (char   *)(FILE_), __LINE__));
12234             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12235             break;
12236           }
12237           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12238           li_flags = GET_DWORD (li_participant_parms[1].info);
12239           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12240           if (sizeof(result) - result_pos < 7)
12241           {
12242             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12243               UnMapId (Id), (char   *)(FILE_), __LINE__));
12244             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12245             break;
12246           }
12247           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12248           if (plci_b != NULL)
12249           {
12250             li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12251             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12252               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12253               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12254             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12255           }
12256           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12257             (&li_req_parms[1].info[1]));
12258         }
12259         result[0] = (byte)(result_pos - 1);
12260         result[3] = (byte)(result_pos - 4);
12261         result[6] = (byte)(result_pos - 7);
12262         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12263         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12264          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12265         {
12266           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12267           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12268         }
12269         else
12270           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12271         plci->li_plci_b_write_pos = plci_b_write_pos;
12272       }
12273       mixer_calculate_coefs (a);
12274       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12275       mixer_notify_update (plci, true);
12276       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12277         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12278       plci->command = 0;
12279       plci->li_cmd = GET_WORD (li_parms[0].info);
12280       start_internal_command (Id, plci, mixer_command);
12281       return (false);
12282
12283     case LI_REQ_DISCONNECT:
12284       if (li_parms[1].length == 4)
12285       {
12286         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12287         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12288         {
12289           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12290             UnMapId (Id), (char   *)(FILE_), __LINE__));
12291           Info = _WRONG_MESSAGE_FORMAT;
12292           break;
12293         }
12294         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12295         Info = li_check_main_plci (Id, plci);
12296         result_buffer[0] = 9;
12297         result_buffer[3] = 6;
12298         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12299         PUT_WORD (&result_buffer[8], GOOD);
12300         if (Info != GOOD)
12301           break;
12302         result = plci->saved_msg.info;
12303         for (i = 0; i <= result_buffer[0]; i++)
12304           result[i] = result_buffer[i];
12305         plci_b_write_pos = plci->li_plci_b_write_pos;
12306         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12307         if (plci_b == NULL)
12308           break;
12309         li_update_connect (Id, a, plci, plci_b_id, false, 0);
12310         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12311         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12312         plci->li_plci_b_write_pos = plci_b_write_pos;
12313       }
12314       else
12315       {
12316         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12317         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12318         {
12319           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12320             UnMapId (Id), (char   *)(FILE_), __LINE__));
12321           Info = _WRONG_MESSAGE_FORMAT;
12322           break;
12323         }
12324         Info = li_check_main_plci (Id, plci);
12325         result_buffer[0] = 7;
12326         result_buffer[3] = 4;
12327         PUT_WORD (&result_buffer[4], Info);
12328         result_buffer[6] = 0;
12329         if (Info != GOOD)
12330           break;
12331         result = plci->saved_msg.info;
12332         for (i = 0; i <= result_buffer[0]; i++)
12333           result[i] = result_buffer[i];
12334         plci_b_write_pos = plci->li_plci_b_write_pos;
12335         participant_parms_pos = 0;
12336         result_pos = 7;
12337         while (participant_parms_pos < li_req_parms[0].length)
12338         {
12339           result[result_pos] = 6;
12340           result_pos += 7;
12341           PUT_DWORD (&result[result_pos - 6], 0);
12342           PUT_WORD (&result[result_pos - 2], GOOD);
12343           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12344             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12345           {
12346             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12347               UnMapId (Id), (char   *)(FILE_), __LINE__));
12348             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12349             break;
12350           }
12351           if (api_parse (&li_participant_struct[0].info[1],
12352             li_participant_struct[0].length, "d", li_participant_parms))
12353           {
12354             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12355               UnMapId (Id), (char   *)(FILE_), __LINE__));
12356             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12357             break;
12358           }
12359           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12360           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12361           if (sizeof(result) - result_pos < 7)
12362           {
12363             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12364               UnMapId (Id), (char   *)(FILE_), __LINE__));
12365             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12366             break;
12367           }
12368           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12369           if (plci_b != NULL)
12370           {
12371             li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12372             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12373             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12374           }
12375           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12376             (&li_req_parms[0].info[1]));
12377         }
12378         result[0] = (byte)(result_pos - 1);
12379         result[3] = (byte)(result_pos - 4);
12380         result[6] = (byte)(result_pos - 7);
12381         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12382         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12383          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12384         {
12385           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12386           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12387         }
12388         else
12389           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12390         plci->li_plci_b_write_pos = plci_b_write_pos;
12391       }
12392       mixer_calculate_coefs (a);
12393       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12394       mixer_notify_update (plci, true);
12395       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12396         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12397       plci->command = 0;
12398       plci->li_cmd = GET_WORD (li_parms[0].info);
12399       start_internal_command (Id, plci, mixer_command);
12400       return (false);
12401
12402     case LI_REQ_SILENT_UPDATE:
12403       if (!plci || !plci->State
12404        || !plci->NL.Id || plci->nl_remove_id
12405        || (plci->li_bchannel_id == 0)
12406        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12407       {
12408         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12409           UnMapId (Id), (char   *)(FILE_), __LINE__));
12410         return (false);
12411       }
12412       plci_b_write_pos = plci->li_plci_b_write_pos;
12413       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12414         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12415       {
12416         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12417           UnMapId (Id), (char   *)(FILE_), __LINE__));
12418         return (false);
12419       }
12420       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12421       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12422        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12423       {
12424         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12425         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12426       }
12427       else
12428         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12429       plci->li_plci_b_write_pos = plci_b_write_pos;
12430       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12431       plci->command = 0;
12432       plci->li_cmd = GET_WORD (li_parms[0].info);
12433       start_internal_command (Id, plci, mixer_command);
12434       return (false);
12435
12436     default:
12437       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12438         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12439       Info = _FACILITY_NOT_SUPPORTED;
12440     }
12441   }
12442   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12443     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12444   return (false);
12445 }
12446
12447
12448 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12449 {
12450   dword d;
12451   DIVA_CAPI_ADAPTER   *a;
12452     byte result[12];
12453
12454   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12455     UnMapId (Id), (char   *)(FILE_), __LINE__));
12456
12457   a = plci->adapter;
12458   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12459   {
12460     do
12461     {
12462       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12463       if (!(d & LI_PLCI_B_SKIP_FLAG))
12464       {
12465         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12466         {
12467           if (d & LI_PLCI_B_DISC_FLAG)
12468           {
12469             result[0] = 5;
12470             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12471             result[3] = 2;
12472             PUT_WORD (&result[4], _LI_USER_INITIATED);
12473           }
12474           else
12475           {
12476             result[0] = 7;
12477             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12478             result[3] = 4;
12479             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12480           }
12481         }
12482         else
12483         {
12484           if (d & LI_PLCI_B_DISC_FLAG)
12485           {
12486             result[0] = 9;
12487             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12488             result[3] = 6;
12489             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12490             PUT_WORD (&result[8], _LI_USER_INITIATED);
12491           }
12492           else
12493           {
12494             result[0] = 7;
12495             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12496             result[3] = 4;
12497             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12498           }
12499         }
12500         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12501           "ws", SELECTOR_LINE_INTERCONNECT, result);
12502       }
12503       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12504         0 : plci->li_plci_b_read_pos + 1;
12505     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12506   }
12507 }
12508
12509
12510 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12511 {
12512   word i, j, ch;
12513   struct xconnect_transfer_address_s s,   *p;
12514   DIVA_CAPI_ADAPTER   *a;
12515
12516   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12517     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12518
12519   a = plci->adapter;
12520   i = 1;
12521   for (i = 1; i < length; i += 16)
12522   {
12523     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12524     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12525     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12526     ch = msg[i+12] | (msg[i+13] << 8);
12527     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12528     if (!a->li_pri && (plci->li_bchannel_id == 2))
12529       j = 1 - j;
12530     j += a->li_base;
12531     if (ch & XCONNECT_CHANNEL_PORT_PC)
12532       p = &(li_config_table[j].send_pc);
12533     else
12534       p = &(li_config_table[j].send_b);
12535     p->card_address.low = s.card_address.low;
12536     p->card_address.high = s.card_address.high;
12537     p->offset = s.offset;
12538     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12539   }
12540   if (plci->internal_command_queue[0]
12541    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12542     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12543     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12544   {
12545     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12546     if (!plci->internal_command)
12547       next_internal_command (Id, plci);
12548   }
12549   mixer_notify_update (plci, true);
12550 }
12551
12552
12553 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12554 {
12555
12556   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12557     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12558
12559 }
12560
12561
12562 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12563 {
12564   word plci_b_write_pos;
12565
12566   plci_b_write_pos = plci->li_plci_b_write_pos;
12567   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12568     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12569   {
12570     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12571       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12572       (char   *)(FILE_), __LINE__));
12573     return (false);
12574   }
12575   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12576   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12577   plci->li_plci_b_write_pos = plci_b_write_pos;
12578   return (true);
12579 }
12580
12581
12582 static void mixer_remove (PLCI   *plci)
12583 {
12584   DIVA_CAPI_ADAPTER   *a;
12585   PLCI   *notify_plci;
12586   dword plci_b_id;
12587   word i, j;
12588
12589   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12590     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12591     (char   *)(FILE_), __LINE__));
12592
12593   a = plci->adapter;
12594   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12595   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12596   {
12597     if ((plci->li_bchannel_id != 0)
12598      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12599     {
12600       i = a->li_base + (plci->li_bchannel_id - 1);
12601       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12602       {
12603         for (j = 0; j < li_total_channels; j++)
12604         {
12605           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12606            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12607           {
12608             notify_plci = li_config_table[j].plci;
12609             if ((notify_plci != NULL)
12610              && (notify_plci != plci)
12611              && (notify_plci->appl != NULL)
12612              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12613              && (notify_plci->State)
12614              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12615             {
12616               mixer_notify_source_removed (notify_plci, plci_b_id);
12617             }
12618           }
12619         }
12620         mixer_clear_config (plci);
12621         mixer_calculate_coefs (a);
12622         mixer_notify_update (plci, true);
12623       }
12624       li_config_table[i].plci = NULL;
12625       plci->li_bchannel_id = 0;
12626     }
12627   }
12628 }
12629
12630
12631 /*------------------------------------------------------------------*/
12632 /* Echo canceller facilities                                        */
12633 /*------------------------------------------------------------------*/
12634
12635
12636 static void ec_write_parameters (PLCI   *plci)
12637 {
12638   word w;
12639     byte parameter_buffer[6];
12640
12641   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12642     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12643     (char   *)(FILE_), __LINE__));
12644
12645   parameter_buffer[0] = 5;
12646   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12647   PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12648   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12649   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12650   PUT_WORD (&parameter_buffer[4], w);
12651   add_p (plci, FTY, parameter_buffer);
12652   sig_req (plci, TEL_CTRL, 0);
12653   send_req (plci);
12654 }
12655
12656
12657 static void ec_clear_config (PLCI   *plci)
12658 {
12659
12660   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12661     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12662     (char   *)(FILE_), __LINE__));
12663
12664   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12665     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12666   plci->ec_tail_length = 0;
12667 }
12668
12669
12670 static void ec_prepare_switch (dword Id, PLCI   *plci)
12671 {
12672
12673   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12674     UnMapId (Id), (char   *)(FILE_), __LINE__));
12675
12676 }
12677
12678
12679 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12680 {
12681
12682   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12683     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12684
12685   return (GOOD);
12686 }
12687
12688
12689 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12690 {
12691   word Info;
12692
12693   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12694     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12695
12696   Info = GOOD;
12697   if (plci->B1_facilities & B1_FACILITY_EC)
12698   {
12699     switch (plci->adjust_b_state)
12700     {
12701     case ADJUST_B_RESTORE_EC_1:
12702       plci->internal_command = plci->adjust_b_command;
12703       if (plci->sig_req)
12704       {
12705         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12706         break;
12707       }
12708       ec_write_parameters (plci);
12709       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12710       break;
12711     case ADJUST_B_RESTORE_EC_2:
12712       if ((Rc != OK) && (Rc != OK_FC))
12713       {
12714         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12715           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12716         Info = _WRONG_STATE;
12717         break;
12718       }
12719       break;
12720     }
12721   }
12722   return (Info);
12723 }
12724
12725
12726 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12727 {
12728   word internal_command, Info;
12729     byte result[8];
12730
12731   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12732     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12733     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12734
12735   Info = GOOD;
12736   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12737   {
12738     result[0] = 2;
12739     PUT_WORD (&result[1], EC_SUCCESS);
12740   }
12741   else
12742   {
12743     result[0] = 5;
12744     PUT_WORD (&result[1], plci->ec_cmd);
12745     result[3] = 2;
12746     PUT_WORD (&result[4], GOOD);
12747   }
12748   internal_command = plci->internal_command;
12749   plci->internal_command = 0;
12750   switch (plci->ec_cmd)
12751   {
12752   case EC_ENABLE_OPERATION:
12753   case EC_FREEZE_COEFFICIENTS:
12754   case EC_RESUME_COEFFICIENT_UPDATE:
12755   case EC_RESET_COEFFICIENTS:
12756     switch (internal_command)
12757     {
12758     default:
12759       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12760         B1_FACILITY_EC), EC_COMMAND_1);
12761     case EC_COMMAND_1:
12762       if (adjust_b_process (Id, plci, Rc) != GOOD)
12763       {
12764         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12765           UnMapId (Id), (char   *)(FILE_), __LINE__));
12766         Info = _FACILITY_NOT_SUPPORTED;
12767         break;
12768       }
12769       if (plci->internal_command)
12770         return;
12771     case EC_COMMAND_2:
12772       if (plci->sig_req)
12773       {
12774         plci->internal_command = EC_COMMAND_2;
12775         return;
12776       }
12777       plci->internal_command = EC_COMMAND_3;
12778       ec_write_parameters (plci);
12779       return;
12780     case EC_COMMAND_3:
12781       if ((Rc != OK) && (Rc != OK_FC))
12782       {
12783         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12784           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12785         Info = _FACILITY_NOT_SUPPORTED;
12786         break;
12787       }
12788       break;
12789     }
12790     break;
12791
12792   case EC_DISABLE_OPERATION:
12793     switch (internal_command)
12794     {
12795     default:
12796     case EC_COMMAND_1:
12797       if (plci->B1_facilities & B1_FACILITY_EC)
12798       {
12799         if (plci->sig_req)
12800         {
12801           plci->internal_command = EC_COMMAND_1;
12802           return;
12803         }
12804         plci->internal_command = EC_COMMAND_2;
12805         ec_write_parameters (plci);
12806         return;
12807       }
12808       Rc = OK;
12809     case EC_COMMAND_2:
12810       if ((Rc != OK) && (Rc != OK_FC))
12811       {
12812         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12813           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12814         Info = _FACILITY_NOT_SUPPORTED;
12815         break;
12816       }
12817       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12818         ~B1_FACILITY_EC), EC_COMMAND_3);
12819     case EC_COMMAND_3:
12820       if (adjust_b_process (Id, plci, Rc) != GOOD)
12821       {
12822         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12823           UnMapId (Id), (char   *)(FILE_), __LINE__));
12824         Info = _FACILITY_NOT_SUPPORTED;
12825         break;
12826       }
12827       if (plci->internal_command)
12828         return;
12829       break;
12830     }
12831     break;
12832   }
12833   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12834     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12835     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12836 }
12837
12838
12839 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12840 {
12841   word Info;
12842   word opt;
12843     API_PARSE ec_parms[3];
12844     byte result[16];
12845
12846   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12847     UnMapId (Id), (char   *)(FILE_), __LINE__));
12848
12849   Info = GOOD;
12850   result[0] = 0;
12851   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12852   {
12853     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12854       UnMapId (Id), (char   *)(FILE_), __LINE__));
12855     Info = _FACILITY_NOT_SUPPORTED;
12856   }
12857   else
12858   {
12859     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12860     {
12861       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12862       {
12863         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12864           UnMapId (Id), (char   *)(FILE_), __LINE__));
12865         Info = _WRONG_MESSAGE_FORMAT;
12866       }
12867       else
12868       {
12869         if (plci == NULL)
12870         {
12871           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12872             UnMapId (Id), (char   *)(FILE_), __LINE__));
12873           Info = _WRONG_IDENTIFIER;
12874         }
12875         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12876         {
12877           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12878             UnMapId (Id), (char   *)(FILE_), __LINE__));
12879           Info = _WRONG_STATE;
12880         }
12881         else
12882         {
12883           plci->command = 0;
12884           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12885           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12886           result[0] = 2;
12887           PUT_WORD (&result[1], EC_SUCCESS);
12888           if (msg[1].length >= 4)
12889           {
12890             opt = GET_WORD (&ec_parms[0].info[2]);
12891             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12892               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12893             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12894               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12895             if (opt & EC_DETECT_DISABLE_TONE)
12896               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12897             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12898               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12899             if (msg[1].length >= 6)
12900             {
12901               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12902             }
12903           }
12904           switch (plci->ec_cmd)
12905           {
12906           case EC_ENABLE_OPERATION:
12907             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12908             start_internal_command (Id, plci, ec_command);
12909             return (false);
12910
12911           case EC_DISABLE_OPERATION:
12912             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12913               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12914               LEC_RESET_COEFFICIENTS;
12915             start_internal_command (Id, plci, ec_command);
12916             return (false);
12917
12918           case EC_FREEZE_COEFFICIENTS:
12919             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12920             start_internal_command (Id, plci, ec_command);
12921             return (false);
12922
12923           case EC_RESUME_COEFFICIENT_UPDATE:
12924             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12925             start_internal_command (Id, plci, ec_command);
12926             return (false);
12927
12928           case EC_RESET_COEFFICIENTS:
12929             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12930             start_internal_command (Id, plci, ec_command);
12931             return (false);
12932
12933           default:
12934             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12935               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12936             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12937           }
12938         }
12939       }
12940     }
12941     else
12942     {
12943       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12944       {
12945         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12946           UnMapId (Id), (char   *)(FILE_), __LINE__));
12947         Info = _WRONG_MESSAGE_FORMAT;
12948       }
12949       else
12950       {
12951         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12952         {
12953           result[0] = 11;
12954           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12955           result[3] = 8;
12956           PUT_WORD (&result[4], GOOD);
12957           PUT_WORD (&result[6], 0x0007);
12958           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12959           PUT_WORD (&result[10], 0);
12960         }
12961         else if (plci == NULL)
12962         {
12963           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12964             UnMapId (Id), (char   *)(FILE_), __LINE__));
12965           Info = _WRONG_IDENTIFIER;
12966         }
12967         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12968         {
12969           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12970             UnMapId (Id), (char   *)(FILE_), __LINE__));
12971           Info = _WRONG_STATE;
12972         }
12973         else
12974         {
12975           plci->command = 0;
12976           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12977           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12978           result[0] = 5;
12979           PUT_WORD (&result[1], plci->ec_cmd);
12980           result[3] = 2;
12981           PUT_WORD (&result[4], GOOD);
12982           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12983             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12984           plci->ec_tail_length = 0;
12985           if (ec_parms[1].length >= 2)
12986           {
12987             opt = GET_WORD (&ec_parms[1].info[1]);
12988             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12989               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12990             if (opt & EC_DETECT_DISABLE_TONE)
12991               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12992             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12993               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12994             if (ec_parms[1].length >= 4)
12995             {
12996               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12997             }
12998           }
12999           switch (plci->ec_cmd)
13000           {
13001           case EC_ENABLE_OPERATION:
13002             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
13003             start_internal_command (Id, plci, ec_command);
13004             return (false);
13005
13006           case EC_DISABLE_OPERATION:
13007             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
13008               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
13009               LEC_RESET_COEFFICIENTS;
13010             start_internal_command (Id, plci, ec_command);
13011             return (false);
13012
13013           default:
13014             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
13015               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
13016             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13017           }
13018         }
13019       }
13020     }
13021   }
13022   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13023     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13024     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13025   return (false);
13026 }
13027
13028
13029 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13030 {
13031     byte result[8];
13032
13033   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13034     UnMapId (Id), (char   *)(FILE_), __LINE__));
13035
13036   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13037   {
13038     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13039     {
13040       result[0] = 2;
13041       PUT_WORD (&result[1], 0);
13042       switch (msg[1])
13043       {
13044       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13046         break;
13047       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13049         break;
13050       case LEC_DISABLE_RELEASED:
13051         PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13052         break;
13053       }
13054     }
13055     else
13056     {
13057       result[0] = 5;
13058       PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13059       result[3] = 2;
13060       PUT_WORD (&result[4], 0);
13061       switch (msg[1])
13062       {
13063       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13064         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13065         break;
13066       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13067         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13068         break;
13069       case LEC_DISABLE_RELEASED:
13070         PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13071         break;
13072       }
13073     }
13074     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13075       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13076   }
13077 }
13078
13079
13080
13081 /*------------------------------------------------------------------*/
13082 /* Advanced voice                                                   */
13083 /*------------------------------------------------------------------*/
13084
13085 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13086 {
13087   DIVA_CAPI_ADAPTER   *a;
13088   word i;
13089   byte *p;
13090
13091   word w, n, j, k;
13092   byte ch_map[MIXER_CHANNELS_BRI];
13093
13094     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13095
13096   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13097     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13098     (char   *)(FILE_), __LINE__, write_command));
13099
13100   a = plci->adapter;
13101   p = coef_buffer + 1;
13102   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13103   i = 0;
13104   while (i + sizeof(word) <= a->adv_voice_coef_length)
13105   {
13106     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13107     p += 2;
13108     i += 2;
13109   }
13110   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13111   {
13112     PUT_WORD (p, 0x8000);
13113     p += 2;
13114     i += 2;
13115   }
13116
13117   if (!a->li_pri && (plci->li_bchannel_id == 0))
13118   {
13119     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13120     {
13121       plci->li_bchannel_id = 1;
13122       li_config_table[a->li_base].plci = plci;
13123       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13124         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13125         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13126     }
13127     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13128     {
13129       plci->li_bchannel_id = 2;
13130       li_config_table[a->li_base + 1].plci = plci;
13131       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13132         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13133         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13134     }
13135   }
13136   if (!a->li_pri && (plci->li_bchannel_id != 0)
13137    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13138   {
13139     i = a->li_base + (plci->li_bchannel_id - 1);
13140     switch (write_command)
13141     {
13142     case ADV_VOICE_WRITE_ACTIVATION:
13143       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13144       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13145       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13146       {
13147         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13148         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13149       }
13150       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13151       {
13152         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13153         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13154         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13155         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13156       }
13157       mixer_calculate_coefs (a);
13158       li_config_table[i].curchnl = li_config_table[i].channel;
13159       li_config_table[j].curchnl = li_config_table[j].channel;
13160       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13161         li_config_table[k].curchnl = li_config_table[k].channel;
13162       break;
13163
13164     case ADV_VOICE_WRITE_DEACTIVATION:
13165       for (j = 0; j < li_total_channels; j++)
13166       {
13167         li_config_table[i].flag_table[j] = 0;
13168         li_config_table[j].flag_table[i] = 0;
13169       }
13170       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13171       for (j = 0; j < li_total_channels; j++)
13172       {
13173         li_config_table[k].flag_table[j] = 0;
13174         li_config_table[j].flag_table[k] = 0;
13175       }
13176       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13177       {
13178         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13179         for (j = 0; j < li_total_channels; j++)
13180         {
13181           li_config_table[k].flag_table[j] = 0;
13182           li_config_table[j].flag_table[k] = 0;
13183         }
13184       }
13185       mixer_calculate_coefs (a);
13186       break;
13187     }
13188     if (plci->B1_facilities & B1_FACILITY_MIXER)
13189     {
13190       w = 0;
13191       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13192         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13193       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13194         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13195       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13196         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13197       *(p++) = (byte) w;
13198       *(p++) = (byte)(w >> 8);
13199       for (j = 0; j < sizeof(ch_map); j += 2)
13200       {
13201         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13202         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13203       }
13204       for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13205       {
13206         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13207         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13208         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13209         {
13210           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13211           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13212           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13213         }
13214         else
13215         {
13216           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13217             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13218         }
13219       }
13220     }
13221     else
13222     {
13223       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13224         *(p++) = a->adv_voice_coef_buffer[i];
13225     }
13226   }
13227   else
13228
13229   {
13230     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13231       *(p++) = a->adv_voice_coef_buffer[i];
13232   }
13233   coef_buffer[0] = (p - coef_buffer) - 1;
13234   add_p (plci, FTY, coef_buffer);
13235   sig_req (plci, TEL_CTRL, 0);
13236   send_req (plci);
13237 }
13238
13239
13240 static void adv_voice_clear_config (PLCI   *plci)
13241 {
13242   DIVA_CAPI_ADAPTER   *a;
13243
13244   word i, j;
13245
13246
13247   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13248     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13249     (char   *)(FILE_), __LINE__));
13250
13251   a = plci->adapter;
13252   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13253   {
13254     a->adv_voice_coef_length = 0;
13255
13256     if (!a->li_pri && (plci->li_bchannel_id != 0)
13257      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13258     {
13259       i = a->li_base + (plci->li_bchannel_id - 1);
13260       li_config_table[i].curchnl = 0;
13261       li_config_table[i].channel = 0;
13262       li_config_table[i].chflags = 0;
13263       for (j = 0; j < li_total_channels; j++)
13264       {
13265         li_config_table[i].flag_table[j] = 0;
13266         li_config_table[j].flag_table[i] = 0;
13267         li_config_table[i].coef_table[j] = 0;
13268         li_config_table[j].coef_table[i] = 0;
13269       }
13270       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13271       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13272       li_config_table[i].curchnl = 0;
13273       li_config_table[i].channel = 0;
13274       li_config_table[i].chflags = 0;
13275       for (j = 0; j < li_total_channels; j++)
13276       {
13277         li_config_table[i].flag_table[j] = 0;
13278         li_config_table[j].flag_table[i] = 0;
13279         li_config_table[i].coef_table[j] = 0;
13280         li_config_table[j].coef_table[i] = 0;
13281       }
13282       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13283       {
13284         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13285         li_config_table[i].curchnl = 0;
13286         li_config_table[i].channel = 0;
13287         li_config_table[i].chflags = 0;
13288         for (j = 0; j < li_total_channels; j++)
13289         {
13290           li_config_table[i].flag_table[j] = 0;
13291           li_config_table[j].flag_table[i] = 0;
13292           li_config_table[i].coef_table[j] = 0;
13293           li_config_table[j].coef_table[i] = 0;
13294         }
13295       }
13296     }
13297
13298   }
13299 }
13300
13301
13302 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13303 {
13304
13305   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13306     UnMapId (Id), (char   *)(FILE_), __LINE__));
13307
13308 }
13309
13310
13311 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13312 {
13313
13314   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13315     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13316
13317   return (GOOD);
13318 }
13319
13320
13321 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13322 {
13323   DIVA_CAPI_ADAPTER   *a;
13324   word Info;
13325
13326   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13327     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13328
13329   Info = GOOD;
13330   a = plci->adapter;
13331   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13332    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13333   {
13334     switch (plci->adjust_b_state)
13335     {
13336     case ADJUST_B_RESTORE_VOICE_1:
13337       plci->internal_command = plci->adjust_b_command;
13338       if (plci->sig_req)
13339       {
13340         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13341         break;
13342       }
13343       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13344       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13345       break;
13346     case ADJUST_B_RESTORE_VOICE_2:
13347       if ((Rc != OK) && (Rc != OK_FC))
13348       {
13349         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13350           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13351         Info = _WRONG_STATE;
13352         break;
13353       }
13354       break;
13355     }
13356   }
13357   return (Info);
13358 }
13359
13360
13361
13362
13363 /*------------------------------------------------------------------*/
13364 /* B1 resource switching                                            */
13365 /*------------------------------------------------------------------*/
13366
13367 static byte b1_facilities_table[] =
13368 {
13369   0x00,  /* 0  No bchannel resources      */
13370   0x00,  /* 1  Codec (automatic law)      */
13371   0x00,  /* 2  Codec (A-law)              */
13372   0x00,  /* 3  Codec (y-law)              */
13373   0x00,  /* 4  HDLC for X.21              */
13374   0x00,  /* 5  HDLC                       */
13375   0x00,  /* 6  External Device 0          */
13376   0x00,  /* 7  External Device 1          */
13377   0x00,  /* 8  HDLC 56k                   */
13378   0x00,  /* 9  Transparent                */
13379   0x00,  /* 10 Loopback to network        */
13380   0x00,  /* 11 Test pattern to net        */
13381   0x00,  /* 12 Rate adaptation sync       */
13382   0x00,  /* 13 Rate adaptation async      */
13383   0x00,  /* 14 R-Interface                */
13384   0x00,  /* 15 HDLC 128k leased line      */
13385   0x00,  /* 16 FAX                        */
13386   0x00,  /* 17 Modem async                */
13387   0x00,  /* 18 Modem sync HDLC            */
13388   0x00,  /* 19 V.110 async HDLC           */
13389   0x12,  /* 20 Adv voice (Trans,mixer)    */
13390   0x00,  /* 21 Codec connected to IC      */
13391   0x0c,  /* 22 Trans,DTMF                 */
13392   0x1e,  /* 23 Trans,DTMF+mixer           */
13393   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13394   0x13,  /* 25 Trans,mixer+local          */
13395   0x12,  /* 26 HDLC,mixer                 */
13396   0x12,  /* 27 HDLC 56k,mixer             */
13397   0x2c,  /* 28 Trans,LEC+DTMF             */
13398   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13399   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13400   0x2c,  /* 31 RTP,LEC+DTMF               */
13401   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13402   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13403   0x00,  /* 34 Signaling task             */
13404   0x00,  /* 35 PIAFS                      */
13405   0x0c,  /* 36 Trans,DTMF+TONE            */
13406   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13407   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13408 };
13409
13410
13411 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13412 {
13413   word b1_facilities;
13414
13415   b1_facilities = b1_facilities_table[b1_resource];
13416   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13417   {
13418
13419     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13420        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13421
13422     {
13423       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13424         b1_facilities |= B1_FACILITY_DTMFX;
13425       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13426         b1_facilities |= B1_FACILITY_DTMFR;
13427     }
13428   }
13429   if ((b1_resource == 17) || (b1_resource == 18))
13430   {
13431     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13432       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13433   }
13434 /*
13435   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13436     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13437     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13438 */
13439   return (b1_facilities);
13440 }
13441
13442
13443 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13444 {
13445   byte b;
13446
13447   switch (b1_resource)
13448   {
13449   case 5:
13450   case 26:
13451     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13452       b = 26;
13453     else
13454       b = 5;
13455     break;
13456
13457   case 8:
13458   case 27:
13459     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13460       b = 27;
13461     else
13462       b = 8;
13463     break;
13464
13465   case 9:
13466   case 20:
13467   case 22:
13468   case 23:
13469   case 24:
13470   case 25:
13471   case 28:
13472   case 29:
13473   case 30:
13474   case 36:
13475   case 37:
13476   case 38:
13477     if (b1_facilities & B1_FACILITY_EC)
13478     {
13479       if (b1_facilities & B1_FACILITY_LOCAL)
13480         b = 30;
13481       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482         b = 29;
13483       else
13484         b = 28;
13485     }
13486
13487     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13488       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13489        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13490     {
13491       if (b1_facilities & B1_FACILITY_LOCAL)
13492         b = 38;
13493       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13494         b = 37;
13495       else
13496         b = 36;
13497     }
13498
13499     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13500       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13501      || ((b1_facilities & B1_FACILITY_DTMFR)
13502       && ((b1_facilities & B1_FACILITY_MIXER)
13503        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13504      || ((b1_facilities & B1_FACILITY_DTMFX)
13505       && ((b1_facilities & B1_FACILITY_MIXER)
13506        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13507     {
13508       if (b1_facilities & B1_FACILITY_LOCAL)
13509         b = 24;
13510       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13511         b = 23;
13512       else
13513         b = 22;
13514     }
13515     else
13516     {
13517       if (b1_facilities & B1_FACILITY_LOCAL)
13518         b = 25;
13519       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520         b = 20;
13521       else
13522         b = 9;
13523     }
13524     break;
13525
13526   case 31:
13527   case 32:
13528   case 33:
13529     if (b1_facilities & B1_FACILITY_LOCAL)
13530       b = 33;
13531     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13532       b = 32;
13533     else
13534       b = 31;
13535     break;
13536
13537   default:
13538     b = b1_resource;
13539   }
13540   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13541     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13542     (char   *)(FILE_), __LINE__,
13543     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13544   return (b);
13545 }
13546
13547
13548 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13549 {
13550   word removed_facilities;
13551
13552   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13553     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13554     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13555     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13556
13557   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13558   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13559
13560   if (removed_facilities & B1_FACILITY_EC)
13561     ec_clear_config (plci);
13562
13563
13564   if (removed_facilities & B1_FACILITY_DTMFR)
13565   {
13566     dtmf_rec_clear_config (plci);
13567     dtmf_parameter_clear_config (plci);
13568   }
13569   if (removed_facilities & B1_FACILITY_DTMFX)
13570     dtmf_send_clear_config (plci);
13571
13572
13573   if (removed_facilities & B1_FACILITY_MIXER)
13574     mixer_clear_config (plci);
13575
13576   if (removed_facilities & B1_FACILITY_VOICE)
13577     adv_voice_clear_config (plci);
13578   plci->B1_facilities = new_b1_facilities;
13579 }
13580
13581
13582 static void adjust_b_clear (PLCI   *plci)
13583 {
13584
13585   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13586     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13587     (char   *)(FILE_), __LINE__));
13588
13589   plci->adjust_b_restore = false;
13590 }
13591
13592
13593 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13594 {
13595   word Info;
13596   byte b1_resource;
13597   NCCI   * ncci_ptr;
13598     API_PARSE bp[2];
13599
13600   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13601     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13602
13603   Info = GOOD;
13604   switch (plci->adjust_b_state)
13605   {
13606   case ADJUST_B_START:
13607     if ((plci->adjust_b_parms_msg == NULL)
13608      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13609      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13610       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13611     {
13612       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13613         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13614       if (b1_resource == plci->B1_resource)
13615       {
13616         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13617         break;
13618       }
13619       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13620       {
13621         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13622           UnMapId (Id), (char   *)(FILE_), __LINE__,
13623           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13624         Info = _WRONG_STATE;
13625         break;
13626       }
13627     }
13628     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13629     {
13630
13631       mixer_prepare_switch (Id, plci);
13632
13633
13634       dtmf_prepare_switch (Id, plci);
13635       dtmf_parameter_prepare_switch (Id, plci);
13636
13637
13638       ec_prepare_switch (Id, plci);
13639
13640       adv_voice_prepare_switch (Id, plci);
13641     }
13642     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13643     Rc = OK;
13644   case ADJUST_B_SAVE_MIXER_1:
13645     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13646     {
13647
13648       Info = mixer_save_config (Id, plci, Rc);
13649       if ((Info != GOOD) || plci->internal_command)
13650         break;
13651
13652     }
13653     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13654     Rc = OK;
13655   case ADJUST_B_SAVE_DTMF_1:
13656     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13657     {
13658
13659       Info = dtmf_save_config (Id, plci, Rc);
13660       if ((Info != GOOD) || plci->internal_command)
13661         break;
13662
13663     }
13664     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13665   case ADJUST_B_REMOVE_L23_1:
13666     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13667      && plci->NL.Id && !plci->nl_remove_id)
13668     {
13669       plci->internal_command = plci->adjust_b_command;
13670       if (plci->adjust_b_ncci != 0)
13671       {
13672         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13673         while (ncci_ptr->data_pending)
13674         {
13675           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13676           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13677         }
13678         while (ncci_ptr->data_ack_pending)
13679           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13680       }
13681       nl_req_ncci (plci, REMOVE,
13682         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13683       send_req (plci);
13684       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13685       break;
13686     }
13687     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13688     Rc = OK;
13689   case ADJUST_B_REMOVE_L23_2:
13690     if ((Rc != OK) && (Rc != OK_FC))
13691     {
13692       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13693         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13694       Info = _WRONG_STATE;
13695       break;
13696     }
13697     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13698     {
13699       if (plci_nl_busy (plci))
13700       {
13701         plci->internal_command = plci->adjust_b_command;
13702         break;
13703       }
13704     }
13705     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13706     Rc = OK;
13707   case ADJUST_B_SAVE_EC_1:
13708     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13709     {
13710
13711       Info = ec_save_config (Id, plci, Rc);
13712       if ((Info != GOOD) || plci->internal_command)
13713         break;
13714
13715     }
13716     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13717     Rc = OK;
13718   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13719     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13720     {
13721
13722       Info = dtmf_parameter_save_config (Id, plci, Rc);
13723       if ((Info != GOOD) || plci->internal_command)
13724         break;
13725
13726     }
13727     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13728     Rc = OK;
13729   case ADJUST_B_SAVE_VOICE_1:
13730     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13731     {
13732       Info = adv_voice_save_config (Id, plci, Rc);
13733       if ((Info != GOOD) || plci->internal_command)
13734         break;
13735     }
13736     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13737   case ADJUST_B_SWITCH_L1_1:
13738     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13739     {
13740       if (plci->sig_req)
13741       {
13742         plci->internal_command = plci->adjust_b_command;
13743         break;
13744       }
13745       if (plci->adjust_b_parms_msg != NULL)
13746         api_load_msg (plci->adjust_b_parms_msg, bp);
13747       else
13748         api_load_msg (&plci->B_protocol, bp);
13749       Info = add_b1 (plci, bp,
13750         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13751         plci->adjust_b_facilities);
13752       if (Info != GOOD)
13753       {
13754         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13755           UnMapId (Id), (char   *)(FILE_), __LINE__,
13756           plci->B1_resource, plci->adjust_b_facilities));
13757         break;
13758       }
13759       plci->internal_command = plci->adjust_b_command;
13760       sig_req (plci, RESOURCES, 0);
13761       send_req (plci);
13762       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13763       break;
13764     }
13765     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13766     Rc = OK;
13767   case ADJUST_B_SWITCH_L1_2:
13768     if ((Rc != OK) && (Rc != OK_FC))
13769     {
13770       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13771         UnMapId (Id), (char   *)(FILE_), __LINE__,
13772         Rc, plci->B1_resource, plci->adjust_b_facilities));
13773       Info = _WRONG_STATE;
13774       break;
13775     }
13776     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13777     Rc = OK;
13778   case ADJUST_B_RESTORE_VOICE_1:
13779   case ADJUST_B_RESTORE_VOICE_2:
13780     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13781     {
13782       Info = adv_voice_restore_config (Id, plci, Rc);
13783       if ((Info != GOOD) || plci->internal_command)
13784         break;
13785     }
13786     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13787     Rc = OK;
13788   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13789   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13790     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13791     {
13792
13793       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13794       if ((Info != GOOD) || plci->internal_command)
13795         break;
13796
13797     }
13798     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13799     Rc = OK;
13800   case ADJUST_B_RESTORE_EC_1:
13801   case ADJUST_B_RESTORE_EC_2:
13802     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13803     {
13804
13805       Info = ec_restore_config (Id, plci, Rc);
13806       if ((Info != GOOD) || plci->internal_command)
13807         break;
13808
13809     }
13810     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13811   case ADJUST_B_ASSIGN_L23_1:
13812     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13813     {
13814       if (plci_nl_busy (plci))
13815       {
13816         plci->internal_command = plci->adjust_b_command;
13817         break;
13818       }
13819       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13820         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13821       if (plci->adjust_b_parms_msg != NULL)
13822         api_load_msg (plci->adjust_b_parms_msg, bp);
13823       else
13824         api_load_msg (&plci->B_protocol, bp);
13825       Info = add_b23 (plci, bp);
13826       if (Info != GOOD)
13827       {
13828         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13829           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13830         break;
13831       }
13832       plci->internal_command = plci->adjust_b_command;
13833       nl_req_ncci (plci, ASSIGN, 0);
13834       send_req (plci);
13835       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13836       break;
13837     }
13838     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13839     Rc = ASSIGN_OK;
13840   case ADJUST_B_ASSIGN_L23_2:
13841     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13842     {
13843       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13844         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13845       Info = _WRONG_STATE;
13846       break;
13847     }
13848     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13849     {
13850       if (Rc != ASSIGN_OK)
13851       {
13852         plci->internal_command = plci->adjust_b_command;
13853         break;
13854       }
13855     }
13856     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13857     {
13858       plci->adjust_b_restore = true;
13859       break;
13860     }
13861     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13862   case ADJUST_B_CONNECT_1:
13863     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13864     {
13865       plci->internal_command = plci->adjust_b_command;
13866       if (plci_nl_busy (plci))
13867         break;
13868       nl_req_ncci (plci, N_CONNECT, 0);
13869       send_req (plci);
13870       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13871       break;
13872     }
13873     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13874     Rc = OK;
13875   case ADJUST_B_CONNECT_2:
13876   case ADJUST_B_CONNECT_3:
13877   case ADJUST_B_CONNECT_4:
13878     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13879     {
13880       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13881         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13882       Info = _WRONG_STATE;
13883       break;
13884     }
13885     if (Rc == OK)
13886     {
13887       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13888       {
13889         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13890         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13891       }
13892       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13893         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13894       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13895         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13896     }
13897     else if (Rc == 0)
13898     {
13899       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13900         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13901       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13902         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13903     }
13904     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13905     {
13906       plci->internal_command = plci->adjust_b_command;
13907       break;
13908     }
13909     Rc = OK;
13910   case ADJUST_B_RESTORE_DTMF_1:
13911   case ADJUST_B_RESTORE_DTMF_2:
13912     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13913     {
13914
13915       Info = dtmf_restore_config (Id, plci, Rc);
13916       if ((Info != GOOD) || plci->internal_command)
13917         break;
13918
13919     }
13920     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13921     Rc = OK;
13922   case ADJUST_B_RESTORE_MIXER_1:
13923   case ADJUST_B_RESTORE_MIXER_2:
13924   case ADJUST_B_RESTORE_MIXER_3:
13925   case ADJUST_B_RESTORE_MIXER_4:
13926   case ADJUST_B_RESTORE_MIXER_5:
13927   case ADJUST_B_RESTORE_MIXER_6:
13928   case ADJUST_B_RESTORE_MIXER_7:
13929     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13930     {
13931
13932       Info = mixer_restore_config (Id, plci, Rc);
13933       if ((Info != GOOD) || plci->internal_command)
13934         break;
13935
13936     }
13937     plci->adjust_b_state = ADJUST_B_END;
13938   case ADJUST_B_END:
13939     break;
13940   }
13941   return (Info);
13942 }
13943
13944
13945 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13946 {
13947
13948   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13949     UnMapId (Id), (char   *)(FILE_), __LINE__,
13950     plci->B1_resource, b1_facilities));
13951
13952   plci->adjust_b_parms_msg = bp_msg;
13953   plci->adjust_b_facilities = b1_facilities;
13954   plci->adjust_b_command = internal_command;
13955   plci->adjust_b_ncci = (word)(Id >> 16);
13956   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13957     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13958   else
13959     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13960   plci->adjust_b_state = ADJUST_B_START;
13961   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13962     UnMapId (Id), (char   *)(FILE_), __LINE__,
13963     plci->B1_resource, b1_facilities));
13964 }
13965
13966
13967 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13968 {
13969   word internal_command;
13970
13971   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13972     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13973
13974   internal_command = plci->internal_command;
13975   plci->internal_command = 0;
13976   switch (internal_command)
13977   {
13978   default:
13979     plci->command = 0;
13980     if (plci->req_in != 0)
13981     {
13982       plci->internal_command = ADJUST_B_RESTORE_1;
13983       break;
13984     }
13985     Rc = OK;
13986   case ADJUST_B_RESTORE_1:
13987     if ((Rc != OK) && (Rc != OK_FC))
13988     {
13989       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13990         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13991     }
13992     plci->adjust_b_parms_msg = NULL;
13993     plci->adjust_b_facilities = plci->B1_facilities;
13994     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13995     plci->adjust_b_ncci = (word)(Id >> 16);
13996     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13997     plci->adjust_b_state = ADJUST_B_START;
13998     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13999       UnMapId (Id), (char   *)(FILE_), __LINE__));
14000   case ADJUST_B_RESTORE_2:
14001     if (adjust_b_process (Id, plci, Rc) != GOOD)
14002     {
14003       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
14004         UnMapId (Id), (char   *)(FILE_), __LINE__));
14005     }
14006     if (plci->internal_command)
14007       break;
14008     break;
14009   }
14010 }
14011
14012
14013 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
14014 {
14015   word Info;
14016   word internal_command;
14017
14018   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14019     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14020
14021   Info = GOOD;
14022   internal_command = plci->internal_command;
14023   plci->internal_command = 0;
14024   switch (internal_command)
14025   {
14026   default:
14027     plci->command = 0;
14028     plci->adjust_b_parms_msg = NULL;
14029     plci->adjust_b_facilities = plci->B1_facilities;
14030     plci->adjust_b_command = RESET_B3_COMMAND_1;
14031     plci->adjust_b_ncci = (word)(Id >> 16);
14032     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14033     plci->adjust_b_state = ADJUST_B_START;
14034     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14035       UnMapId (Id), (char   *)(FILE_), __LINE__));
14036   case RESET_B3_COMMAND_1:
14037     Info = adjust_b_process (Id, plci, Rc);
14038     if (Info != GOOD)
14039     {
14040       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14041         UnMapId (Id), (char   *)(FILE_), __LINE__));
14042       break;
14043     }
14044     if (plci->internal_command)
14045       return;
14046     break;
14047   }
14048 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14049   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14050 }
14051
14052
14053 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14054 {
14055   word Info;
14056   word internal_command;
14057   byte esc_chi[3];
14058
14059   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14060     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14061
14062   Info = GOOD;
14063   internal_command = plci->internal_command;
14064   plci->internal_command = 0;
14065   switch (internal_command)
14066   {
14067   default:
14068     plci->command = 0;
14069     plci->adjust_b_parms_msg = &plci->saved_msg;
14070     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14071       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14072     else
14073       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14074     plci->adjust_b_command = SELECT_B_COMMAND_1;
14075     plci->adjust_b_ncci = (word)(Id >> 16);
14076     if (plci->saved_msg.parms[0].length == 0)
14077     {
14078       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14079         ADJUST_B_MODE_NO_RESOURCE;
14080     }
14081     else
14082     {
14083       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14084         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14085     }
14086     plci->adjust_b_state = ADJUST_B_START;
14087     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14088       UnMapId (Id), (char   *)(FILE_), __LINE__));
14089   case SELECT_B_COMMAND_1:
14090     Info = adjust_b_process (Id, plci, Rc);
14091     if (Info != GOOD)
14092     {
14093       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14094         UnMapId (Id), (char   *)(FILE_), __LINE__));
14095       break;
14096     }
14097     if (plci->internal_command)
14098       return;
14099     if (plci->tel == ADV_VOICE)
14100     {
14101       esc_chi[0] = 0x02;
14102       esc_chi[1] = 0x18;
14103       esc_chi[2] = plci->b_channel;
14104       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14105     }
14106     break;
14107   }
14108   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14109 }
14110
14111
14112 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14113 {
14114   word Info;
14115   word internal_command;
14116
14117   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14118     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14119
14120   Info = GOOD;
14121   internal_command = plci->internal_command;
14122   plci->internal_command = 0;
14123   switch (internal_command)
14124   {
14125   default:
14126     plci->command = 0;
14127   case FAX_CONNECT_ACK_COMMAND_1:
14128     if (plci_nl_busy (plci))
14129     {
14130       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14131       return;
14132     }
14133     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14134     plci->NData[0].P = plci->fax_connect_info_buffer;
14135     plci->NData[0].PLength = plci->fax_connect_info_length;
14136     plci->NL.X = plci->NData;
14137     plci->NL.ReqCh = 0;
14138     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14139     plci->adapter->request (&plci->NL);
14140     return;
14141   case FAX_CONNECT_ACK_COMMAND_2:
14142     if ((Rc != OK) && (Rc != OK_FC))
14143     {
14144       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14145         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14146       break;
14147     }
14148   }
14149   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14150    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14151   {
14152     if (plci->B3_prot == 4)
14153       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14154     else
14155       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14156     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14157   }
14158 }
14159
14160
14161 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14162 {
14163   word Info;
14164   word internal_command;
14165
14166   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14167     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14168
14169   Info = GOOD;
14170   internal_command = plci->internal_command;
14171   plci->internal_command = 0;
14172   switch (internal_command)
14173   {
14174   default:
14175     plci->command = 0;
14176   case FAX_EDATA_ACK_COMMAND_1:
14177     if (plci_nl_busy (plci))
14178     {
14179       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14180       return;
14181     }
14182     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14183     plci->NData[0].P = plci->fax_connect_info_buffer;
14184     plci->NData[0].PLength = plci->fax_edata_ack_length;
14185     plci->NL.X = plci->NData;
14186     plci->NL.ReqCh = 0;
14187     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14188     plci->adapter->request (&plci->NL);
14189     return;
14190   case FAX_EDATA_ACK_COMMAND_2:
14191     if ((Rc != OK) && (Rc != OK_FC))
14192     {
14193       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14194         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14195       break;
14196     }
14197   }
14198 }
14199
14200
14201 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14202 {
14203   word Info;
14204   word internal_command;
14205
14206   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14207     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14208
14209   Info = GOOD;
14210   internal_command = plci->internal_command;
14211   plci->internal_command = 0;
14212   switch (internal_command)
14213   {
14214   default:
14215     plci->command = 0;
14216   case FAX_CONNECT_INFO_COMMAND_1:
14217     if (plci_nl_busy (plci))
14218     {
14219       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14220       return;
14221     }
14222     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14223     plci->NData[0].P = plci->fax_connect_info_buffer;
14224     plci->NData[0].PLength = plci->fax_connect_info_length;
14225     plci->NL.X = plci->NData;
14226     plci->NL.ReqCh = 0;
14227     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14228     plci->adapter->request (&plci->NL);
14229     return;
14230   case FAX_CONNECT_INFO_COMMAND_2:
14231     if ((Rc != OK) && (Rc != OK_FC))
14232     {
14233       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14234         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14235       Info = _WRONG_STATE;
14236       break;
14237     }
14238     if (plci_nl_busy (plci))
14239     {
14240       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14241       return;
14242     }
14243     plci->command = _CONNECT_B3_R;
14244     nl_req_ncci (plci, N_CONNECT, 0);
14245     send_req (plci);
14246     return;
14247   }
14248   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14249 }
14250
14251
14252 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14253 {
14254   word Info;
14255   word internal_command;
14256
14257   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14258     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14259
14260   Info = GOOD;
14261   internal_command = plci->internal_command;
14262   plci->internal_command = 0;
14263   switch (internal_command)
14264   {
14265   default:
14266     plci->command = 0;
14267     plci->adjust_b_parms_msg = NULL;
14268     plci->adjust_b_facilities = plci->B1_facilities;
14269     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14270     plci->adjust_b_ncci = (word)(Id >> 16);
14271     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14272     plci->adjust_b_state = ADJUST_B_START;
14273     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14274       UnMapId (Id), (char   *)(FILE_), __LINE__));
14275   case FAX_ADJUST_B23_COMMAND_1:
14276     Info = adjust_b_process (Id, plci, Rc);
14277     if (Info != GOOD)
14278     {
14279       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14280         UnMapId (Id), (char   *)(FILE_), __LINE__));
14281       break;
14282     }
14283     if (plci->internal_command)
14284       return;
14285   case FAX_ADJUST_B23_COMMAND_2:
14286     if (plci_nl_busy (plci))
14287     {
14288       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14289       return;
14290     }
14291     plci->command = _CONNECT_B3_R;
14292     nl_req_ncci (plci, N_CONNECT, 0);
14293     send_req (plci);
14294     return;
14295   }
14296   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14297 }
14298
14299
14300 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14301 {
14302   word internal_command;
14303
14304   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14305     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14306
14307   internal_command = plci->internal_command;
14308   plci->internal_command = 0;
14309   switch (internal_command)
14310   {
14311   default:
14312     plci->command = 0;
14313     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14314     return;
14315   case FAX_DISCONNECT_COMMAND_1:
14316   case FAX_DISCONNECT_COMMAND_2:
14317   case FAX_DISCONNECT_COMMAND_3:
14318     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14319     {
14320       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14321         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14322       break;
14323     }
14324     if (Rc == OK)
14325     {
14326       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14327        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14328       {
14329         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14330       }
14331     }
14332     else if (Rc == 0)
14333     {
14334       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14335         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14336     }
14337     return;
14338   }
14339 }
14340
14341
14342
14343 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14344 {
14345   word Info;
14346   word internal_command;
14347
14348   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14349     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14350
14351   Info = GOOD;
14352   internal_command = plci->internal_command;
14353   plci->internal_command = 0;
14354   switch (internal_command)
14355   {
14356   default:
14357     plci->command = 0;
14358   case RTP_CONNECT_B3_REQ_COMMAND_1:
14359     if (plci_nl_busy (plci))
14360     {
14361       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14362       return;
14363     }
14364     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14365     nl_req_ncci (plci, N_CONNECT, 0);
14366     send_req (plci);
14367     return;
14368   case RTP_CONNECT_B3_REQ_COMMAND_2:
14369     if ((Rc != OK) && (Rc != OK_FC))
14370     {
14371       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14372         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14373       Info = _WRONG_STATE;
14374       break;
14375     }
14376     if (plci_nl_busy (plci))
14377     {
14378       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14379       return;
14380     }
14381     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14382     plci->NData[0].PLength = plci->internal_req_buffer[0];
14383     plci->NData[0].P = plci->internal_req_buffer + 1;
14384     plci->NL.X = plci->NData;
14385     plci->NL.ReqCh = 0;
14386     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14387     plci->adapter->request (&plci->NL);
14388     break;
14389   case RTP_CONNECT_B3_REQ_COMMAND_3:
14390     return;
14391   }
14392   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14393 }
14394
14395
14396 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14397 {
14398   word Info;
14399   word internal_command;
14400
14401   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14402     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14403
14404   Info = GOOD;
14405   internal_command = plci->internal_command;
14406   plci->internal_command = 0;
14407   switch (internal_command)
14408   {
14409   default:
14410     plci->command = 0;
14411   case RTP_CONNECT_B3_RES_COMMAND_1:
14412     if (plci_nl_busy (plci))
14413     {
14414       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14415       return;
14416     }
14417     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14418     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14419     send_req (plci);
14420     return;
14421   case RTP_CONNECT_B3_RES_COMMAND_2:
14422     if ((Rc != OK) && (Rc != OK_FC))
14423     {
14424       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14425         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14426       Info = _WRONG_STATE;
14427       break;
14428     }
14429     if (plci_nl_busy (plci))
14430     {
14431       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14432       return;
14433     }
14434     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14435     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14436     plci->NData[0].PLength = plci->internal_req_buffer[0];
14437     plci->NData[0].P = plci->internal_req_buffer + 1;
14438     plci->NL.X = plci->NData;
14439     plci->NL.ReqCh = 0;
14440     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14441     plci->adapter->request (&plci->NL);
14442     return;
14443   case RTP_CONNECT_B3_RES_COMMAND_3:
14444     return;
14445   }
14446 }
14447
14448
14449
14450 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14451 {
14452     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14453   word Info;
14454   word internal_command;
14455
14456   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14457     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14458
14459   Info = GOOD;
14460   internal_command = plci->internal_command;
14461   plci->internal_command = 0;
14462   switch (internal_command)
14463   {
14464   default:
14465     if (!plci->NL.Id)
14466       break;
14467     plci->command = 0;
14468     plci->adjust_b_parms_msg = NULL;
14469     plci->adjust_b_facilities = plci->B1_facilities;
14470     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14471     plci->adjust_b_ncci = (word)(Id >> 16);
14472     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14473     plci->adjust_b_state = ADJUST_B_START;
14474     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14475       UnMapId (Id), (char   *)(FILE_), __LINE__));
14476   case HOLD_SAVE_COMMAND_1:
14477     Info = adjust_b_process (Id, plci, Rc);
14478     if (Info != GOOD)
14479     {
14480       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14481         UnMapId (Id), (char   *)(FILE_), __LINE__));
14482       break;
14483     }
14484     if (plci->internal_command)
14485       return;
14486   }
14487   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14488 }
14489
14490
14491 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14492 {
14493     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14494   word Info;
14495   word internal_command;
14496
14497   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14498     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14499
14500   Info = GOOD;
14501   internal_command = plci->internal_command;
14502   plci->internal_command = 0;
14503   switch (internal_command)
14504   {
14505   default:
14506     plci->command = 0;
14507     plci->adjust_b_parms_msg = NULL;
14508     plci->adjust_b_facilities = plci->B1_facilities;
14509     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14510     plci->adjust_b_ncci = (word)(Id >> 16);
14511     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14512     plci->adjust_b_state = ADJUST_B_START;
14513     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14514       UnMapId (Id), (char   *)(FILE_), __LINE__));
14515   case RETRIEVE_RESTORE_COMMAND_1:
14516     Info = adjust_b_process (Id, plci, Rc);
14517     if (Info != GOOD)
14518     {
14519       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14520         UnMapId (Id), (char   *)(FILE_), __LINE__));
14521       break;
14522     }
14523     if (plci->internal_command)
14524       return;
14525   }
14526   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14527 }
14528
14529
14530 static void init_b1_config (PLCI   *plci)
14531 {
14532
14533   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14534     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14535     (char   *)(FILE_), __LINE__));
14536
14537   plci->B1_resource = 0;
14538   plci->B1_facilities = 0;
14539
14540   plci->li_bchannel_id = 0;
14541   mixer_clear_config (plci);
14542
14543
14544   ec_clear_config (plci);
14545
14546
14547   dtmf_rec_clear_config (plci);
14548   dtmf_send_clear_config (plci);
14549   dtmf_parameter_clear_config (plci);
14550
14551   adv_voice_clear_config (plci);
14552   adjust_b_clear (plci);
14553 }
14554
14555
14556 static void clear_b1_config (PLCI   *plci)
14557 {
14558
14559   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14560     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14561     (char   *)(FILE_), __LINE__));
14562
14563   adv_voice_clear_config (plci);
14564   adjust_b_clear (plci);
14565
14566   ec_clear_config (plci);
14567
14568
14569   dtmf_rec_clear_config (plci);
14570   dtmf_send_clear_config (plci);
14571   dtmf_parameter_clear_config (plci);
14572
14573
14574   if ((plci->li_bchannel_id != 0)
14575    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14576   {
14577     mixer_clear_config (plci);
14578     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14579     plci->li_bchannel_id = 0;
14580   }
14581
14582   plci->B1_resource = 0;
14583   plci->B1_facilities = 0;
14584 }
14585
14586
14587 /* -----------------------------------------------------------------
14588                 XON protocol local helpers
14589    ----------------------------------------------------------------- */
14590 static void channel_flow_control_remove (PLCI   * plci) {
14591   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14592   word i;
14593   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14594     if (a->ch_flow_plci[i] == plci->Id) {
14595       a->ch_flow_plci[i] = 0;
14596       a->ch_flow_control[i] = 0;
14597     }
14598   }
14599 }
14600
14601 static void channel_x_on (PLCI   * plci, byte ch) {
14602   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14603   if (a->ch_flow_control[ch] & N_XON_SENT) {
14604     a->ch_flow_control[ch] &= ~N_XON_SENT;
14605   }
14606 }
14607
14608 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14609   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14610   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14611     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14612     a->ch_flow_plci[ch] = plci->Id;
14613     a->ch_flow_control_pending++;
14614   }
14615 }
14616
14617 static void channel_request_xon (PLCI   * plci, byte ch) {
14618   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14619
14620   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14621     a->ch_flow_control[ch] |= N_XON_REQ;
14622     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14623     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14624   }
14625 }
14626
14627 static void channel_xmit_extended_xon (PLCI   * plci) {
14628   DIVA_CAPI_ADAPTER   * a;
14629   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14630   int i, one_requested = 0;
14631
14632   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14633     return;
14634   }
14635
14636   for (i = 0; i < max_ch; i++) {
14637     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14638         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14639         (plci->Id == a->ch_flow_plci[i])) {
14640       channel_request_xon (plci, (byte)i);
14641       one_requested = 1;
14642     }
14643   }
14644
14645   if (one_requested) {
14646     channel_xmit_xon (plci);
14647   }
14648 }
14649
14650 /*
14651   Try to xmit next X_ON
14652   */
14653 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14654   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14655   int i;
14656
14657   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14658     return (0);
14659   }
14660
14661   if (a->last_flow_control_ch >= max_ch) {
14662     a->last_flow_control_ch = 1;
14663   }
14664   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14665     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14666         (plci->Id == a->ch_flow_plci[i])) {
14667       a->last_flow_control_ch = i+1;
14668       return (i);
14669     }
14670   }
14671
14672   for (i = 1; i < a->last_flow_control_ch; i++) {
14673     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14674         (plci->Id == a->ch_flow_plci[i])) {
14675       a->last_flow_control_ch = i+1;
14676       return (i);
14677     }
14678   }
14679
14680   return (0);
14681 }
14682
14683 static void channel_xmit_xon (PLCI   * plci) {
14684   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14685   byte ch;
14686
14687   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14688     return;
14689   }
14690   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14691     return;
14692   }
14693   a->ch_flow_control[ch] &= ~N_XON_REQ;
14694   a->ch_flow_control[ch] |= N_XON_SENT;
14695
14696   plci->NL.Req = plci->nl_req = (byte)N_XON;
14697   plci->NL.ReqCh         = ch;
14698   plci->NL.X             = plci->NData;
14699   plci->NL.XNum          = 1;
14700   plci->NData[0].P       = &plci->RBuffer[0];
14701   plci->NData[0].PLength = 0;
14702
14703   plci->adapter->request(&plci->NL);
14704 }
14705
14706 static int channel_can_xon (PLCI   * plci, byte ch) {
14707   APPL   * APPLptr;
14708   DIVA_CAPI_ADAPTER   * a;
14709   word NCCIcode;
14710   dword count;
14711   word Num;
14712   word i;
14713
14714   APPLptr = plci->appl;
14715   a = plci->adapter;
14716
14717   if (!APPLptr)
14718     return (0);
14719
14720   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14721
14722                 /* count all buffers within the Application pool    */
14723                 /* belonging to the same NCCI. XON if a first is    */
14724                 /* used.                                            */
14725   count = 0;
14726   Num = 0xffff;
14727   for(i=0; i<APPLptr->MaxBuffer; i++) {
14728     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14729     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14730   }
14731   if ((count > 2) || (Num == 0xffff)) {
14732     return (0);
14733   }
14734   return (1);
14735 }
14736
14737
14738 /*------------------------------------------------------------------*/
14739
14740 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14741 {
14742   return 1;
14743 }
14744
14745
14746
14747 /**********************************************************************************/
14748 /* function groups the listening applications according to the CIP mask and the   */
14749 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14750 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14751 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14752 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14753 /* OS specific part (per adapter).                                                */
14754 /**********************************************************************************/
14755 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14756 {
14757   word i,j,k,busy,group_found;
14758   dword info_mask_group[MAX_CIP_TYPES];
14759   dword cip_mask_group[MAX_CIP_TYPES];
14760   word appl_number_group_type[MAX_APPL];
14761   PLCI   *auxplci;
14762
14763   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14764
14765   if(!a->group_optimization_enabled)
14766   {
14767     dbug(1,dprintf("No group optimization"));
14768     return;
14769   }
14770
14771   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14772
14773   for(i=0;i<MAX_CIP_TYPES;i++)
14774   {
14775     info_mask_group[i] = 0;
14776     cip_mask_group [i] = 0;
14777   }
14778   for(i=0;i<MAX_APPL;i++)
14779   {
14780     appl_number_group_type[i] = 0;
14781   }
14782   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14783   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14784     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14785     {
14786       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14787       return; /* allow good application unfiltered access */
14788     }
14789   }
14790   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14791   {
14792     if(application[i].Id && a->CIP_Mask[i] )
14793     {
14794       for(k=0,busy=false; k<a->max_plci; k++)
14795       {
14796         if(a->plci[k].Id) 
14797         {
14798           auxplci = &a->plci[k];
14799           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14800           {
14801             busy = true;
14802             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14803           }
14804           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14805           {
14806             busy = true;
14807             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14808           }
14809         }
14810       }
14811
14812       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14813       {
14814         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14815         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14816           appl_number_group_type[i] = MAX_CIP_TYPES;
14817           group_found=true;
14818           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14819         }
14820         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14821         {                                      /* is group already present ?                  */
14822           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14823           group_found=true;
14824           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]));
14825         }
14826         else if(!info_mask_group[j])
14827         {                                      /* establish a new group                       */
14828           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14829           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14830           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14831           group_found=true;
14832           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]));
14833         }
14834       }
14835     }
14836   }
14837         
14838   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14839   {
14840     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14841     {
14842       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14843       {
14844         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14845       }
14846       else
14847       {
14848         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14849         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14850         {
14851           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14852           {
14853             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14854             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14855             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14856           }
14857         }
14858       }
14859     }
14860     else                                                 /* application should not get a call */
14861     {
14862       clear_group_ind_mask_bit (plci, i);
14863     }
14864   }
14865
14866 }
14867
14868
14869
14870 /* OS notifies the driver about a application Capi_Register */
14871 word CapiRegister(word id)
14872 {
14873   word i,j,appls_found;
14874
14875   PLCI   *plci;
14876   DIVA_CAPI_ADAPTER   *a;
14877
14878   for(i=0,appls_found=0; i<max_appl; i++)
14879   {
14880     if( application[i].Id && (application[i].Id!=id) )
14881     {
14882       appls_found++;                       /* an application has been found */
14883     }
14884   }
14885
14886   if(appls_found) return true;
14887   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14888   {
14889     a = &adapter[i];
14890     if(a->request)
14891     {
14892       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14893       {
14894         if(!appls_found)           /* first application does a capi register   */
14895         {
14896           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14897           {
14898             plci = &a->plci[j-1];
14899             plci->command = 0;
14900             add_p(plci,OAD,"\x01\xfd");
14901             add_p(plci,CAI,"\x01\x80");
14902             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14903             add_p(plci,SHIFT|6,NULL);
14904             add_p(plci,SIN,"\x02\x00\x00");
14905             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14906             sig_req(plci,ASSIGN,DSIG_ID);
14907             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14908             sig_req(plci,SIG_CTRL,0);
14909             send_req(plci);
14910           }
14911         }
14912       }
14913     }
14914   }
14915   return false;
14916 }
14917
14918 /*------------------------------------------------------------------*/
14919
14920 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14921
14922 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14923 {
14924  word i;
14925  /* Format of vswitch_t:
14926  0 byte length
14927  1 byte VSWITCHIE
14928  2 byte VSWITCH_REQ/VSWITCH_IND
14929  3 byte reserved
14930  4 word VSwitchcommand
14931  6 word returnerror
14932  8... Params
14933  */
14934  if(!plci ||
14935   !plci->appl ||
14936   !plci->State ||
14937   plci->Sig.Ind==NCR_FACILITY
14938   )
14939   return;
14940  
14941  for(i=0;i<MAX_MULTI_IE;i++)
14942  {
14943         if(!parms[i][0]) continue;
14944   if(parms[i][0]<7)
14945   {
14946    parms[i][0]=0; /* kill it */
14947    continue;
14948   }
14949   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14950   switch(parms[i][4])
14951   {
14952   case VSJOIN:
14953    if(!plci->relatedPTYPLCI ||
14954     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14955    { /* Error */
14956     break;
14957    }
14958    /* remember all necessary informations */
14959    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14960    {
14961     break;
14962    }
14963    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14964    {   /* first indication after ECT-Request on Consultation Call */
14965     plci->vswitchstate=parms[i][9];
14966     parms[i][9]=2; /* State */
14967     /* now ask first Call to join */
14968    }
14969    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14970    { /* Answer of VSWITCH_REQ from first Call */
14971     plci->vswitchstate=parms[i][9];
14972     /* tell consultation call to join
14973     and the protocol capabilities of the first call */
14974    }
14975    else
14976    { /* Error */
14977     break;
14978    }    
14979    plci->vsprot=parms[i][10]; /* protocol */
14980    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14981    /* send join request to related PLCI */
14982    parms[i][1]=VSWITCHIE;
14983    parms[i][2]=VSWITCH_REQ;
14984    
14985    plci->relatedPTYPLCI->command = 0;
14986    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14987    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14988    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14989    send_req(plci->relatedPTYPLCI);
14990    break;
14991   case VSTRANSPORT:
14992   default:
14993    if(plci->relatedPTYPLCI &&
14994     plci->vswitchstate==3 &&
14995     plci->relatedPTYPLCI->vswitchstate==3)
14996    {
14997     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14998     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14999     send_req(plci->relatedPTYPLCI);
15000    }
15001    break;
15002   }  
15003   parms[i][0]=0; /* kill it */
15004  }
15005 }
15006
15007
15008 /*------------------------------------------------------------------*/
15009
15010 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
15011   ENTITY e;
15012   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15013
15014   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15015     return (-1);
15016   }
15017
15018   pReq->xdi_dma_descriptor_operation.Req = 0;
15019   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15020
15021   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15022   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15023   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15024   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15025
15026   e.user[0] = plci->adapter->Id - 1;
15027   plci->adapter->request((ENTITY*)pReq);
15028
15029   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15030       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15031       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15032     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15033     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15034          plci->adapter->Id,
15035          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15036          *dma_magic));
15037     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15038   } else {
15039     dbug(1,dprintf("dma_alloc failed"));
15040     return (-1);
15041   }
15042 }
15043
15044 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15045   ENTITY e;
15046   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15047
15048   if (nr < 0) {
15049     return;
15050   }
15051
15052   pReq->xdi_dma_descriptor_operation.Req = 0;
15053   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15054
15055   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15056   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15057   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15058   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15059
15060   e.user[0] = plci->adapter->Id - 1;
15061   plci->adapter->request((ENTITY*)pReq);
15062
15063   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15064     dbug(1,dprintf("dma_free(%d)", nr));
15065   } else {
15066     dbug(1,dprintf("dma_free failed (%d)", nr));
15067   }
15068 }
15069
15070 /*------------------------------------------------------------------*/