Merge branch 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[sfrench/cifs-2.6.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3   Copyright (c) Eicon Networks, 2002.
4  *
5   This source file is supplied for the use with
6   Eicon Networks range of DIVA Server Adapters.
7  *
8   Eicon File Revision :    2.1
9  *
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2, or (at your option)
13   any later version.
14  *
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18   See the GNU General Public License for more details.
19  *
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67  */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
75 static void set_group_ind_mask (PLCI   *plci);
76 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
77 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL   *, CAPI_MSG   *);
82 static word api_parse(byte   *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
84 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI   *);
90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
92
93 void   callback(ENTITY   *);
94
95 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI   *, byte);
97 static void data_ack(PLCI   *, byte);
98 static void sig_ind(PLCI   *);
99 static void SendInfo(PLCI   *, dword, byte   * *, byte);
100 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
101 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
102
103 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
104
105 static void nl_ind(PLCI   *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER   *);
133 static void add_p(PLCI   *, byte, byte   *);
134 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
137 static void add_d(PLCI   *, word, byte   *);
138 static void add_ai(PLCI   *, API_PARSE *);
139 static word add_b1(PLCI   *, API_PARSE *, word, word);
140 static word add_b23(PLCI   *, API_PARSE *);
141 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI   *, byte, byte);
143 static void nl_req_ncci(PLCI   *, byte, byte);
144 static void send_req(PLCI   *);
145 static void send_data(PLCI   *);
146 static word plci_remove_check(PLCI   *);
147 static void listen_check(DIVA_CAPI_ADAPTER   *);
148 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI   *, word *, byte   **, byte);
151 static byte ie_compare(byte   *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
153 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
154
155 /*
156   XON protocol helpers
157   */
158 static void channel_flow_control_remove (PLCI   * plci);
159 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI   * plci, byte ch);
161 static void channel_request_xon (PLCI   * plci, byte ch);
162 static void channel_xmit_xon (PLCI   * plci);
163 static int channel_can_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI   * plci);
165
166 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
169 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
170 static void VoiceChannelOff(PLCI   *plci);
171 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
172 static void adv_voice_clear_config (PLCI   *plci);
173
174 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
189 static void init_b1_config (PLCI   *plci);
190 static void clear_b1_config (PLCI   *plci);
191
192 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI   *plci);
195 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
196 static void dtmf_parameter_write (PLCI   *plci);
197
198
199 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
201 static void mixer_clear_config (PLCI   *plci);
202 static void mixer_notify_update (PLCI   *plci, byte others);
203 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_remove (PLCI   *plci);
209
210
211 static void ec_command (dword Id, PLCI   *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
214
215
216 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
218
219
220 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
221 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231
232 void   sendf(APPL   *, word, dword, word, byte *, ...);
233 void   * TransmitBufferSet(APPL   * appl, dword ref);
234 void   * TransmitBufferGet(APPL   * appl, void   * p);
235 void TransmitBufferFree(APPL   * appl, void   * p);
236 void   * ReceiveBufferGet(APPL   * appl, int Num);
237
238 int fax_head_line_time (char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER   * adapter;
247 extern APPL   * application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260   word command;
261   byte * format;
262   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
263 } ftable[] = {
264   {_DATA_B3_R,                          "dwww",         data_b3_req},
265   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
266   {_INFO_R,                             "ss",           info_req},
267   {_INFO_I|RESPONSE,                    "",             info_res},
268   {_CONNECT_R,                          "wsssssssss",   connect_req},
269   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
270   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
271   {_DISCONNECT_R,                       "s",            disconnect_req},
272   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
273   {_LISTEN_R,                           "dddss",        listen_req},
274   {_ALERT_R,                            "s",            alert_req},
275   {_FACILITY_R,                         "ws",           facility_req},
276   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
277   {_CONNECT_B3_R,                       "s",            connect_b3_req},
278   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
279   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
280   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
282   {_RESET_B3_R,                         "s",            reset_b3_req},
283   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
284   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
286   {_SELECT_B_REQ,                       "s",            select_b_req},
287   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
289   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
290 };
291
292 static byte * cip_bc[29][2] = {
293   { "",                     ""                     }, /* 0 */
294   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303   { "",                     ""                     }, /* 10 */
304   { "",                     ""                     }, /* 11 */
305   { "",                     ""                     }, /* 12 */
306   { "",                     ""                     }, /* 13 */
307   { "",                     ""                     }, /* 14 */
308   { "",                     ""                     }, /* 15 */
309
310   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte * cip_hlc[29] = {
326   "",                           /* 0 */
327   "",                           /* 1 */
328   "",                           /* 2 */
329   "",                           /* 3 */
330   "",                           /* 4 */
331   "",                           /* 5 */
332   "",                           /* 6 */
333   "",                           /* 7 */
334   "",                           /* 8 */
335   "",                           /* 9 */
336   "",                           /* 10 */
337   "",                           /* 11 */
338   "",                           /* 12 */
339   "",                           /* 13 */
340   "",                           /* 14 */
341   "",                           /* 15 */
342
343   "\x02\x91\x81",               /* 16 */
344   "\x02\x91\x84",               /* 17 */
345   "\x02\x91\xa1",               /* 18 */
346   "\x02\x91\xa4",               /* 19 */
347   "\x02\x91\xa8",               /* 20 */
348   "\x02\x91\xb1",               /* 21 */
349   "\x02\x91\xb2",               /* 22 */
350   "\x02\x91\xb5",               /* 23 */
351   "\x02\x91\xb8",               /* 24 */
352   "\x02\x91\xc1",               /* 25 */
353   "\x02\x91\x81",               /* 26 */
354   "\x03\x91\xe0\x01",           /* 27 */
355   "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL   * appl, CAPI_MSG   * msg)
387 {
388   word i, j, k, l, n;
389   word ret;
390   byte c;
391   byte controller;
392   DIVA_CAPI_ADAPTER   * a;
393   PLCI   * plci;
394   NCCI   * ncci_ptr;
395   word ncci;
396   CAPI_MSG   *m;
397     API_PARSE msg_parms[MAX_MSG_PARMS+1];
398
399   if (msg->header.length < sizeof (msg->header) ||
400       msg->header.length > MAX_MSG_SIZE) {
401     dbug(1,dprintf("bad len"));
402     return _BAD_MSG;
403   }
404
405   controller = (byte)((msg->header.controller &0x7f)-1);
406
407   /* controller starts with 0 up to (max_adapter - 1) */
408   if ( controller >= max_adapter )
409   {
410     dbug(1,dprintf("invalid ctrl"));
411     return _BAD_MSG;
412   }
413   
414   a = &adapter[controller];
415   plci = NULL;
416   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417   {
418     dbug(1,dprintf("plci=%x",msg->header.plci));
419     plci = &a->plci[msg->header.plci-1];
420     ncci = GET_WORD(&msg->header.ncci);
421     if (plci->Id
422      && (plci->appl
423       || (plci->State == INC_CON_PENDING)
424       || (plci->State == INC_CON_ALERT)
425       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426      && ((ncci == 0)
427       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429     {
430       i = plci->msg_in_read_pos;
431       j = plci->msg_in_write_pos;
432       if (j >= i)
433       {
434         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435           i += MSG_IN_QUEUE_SIZE - j;
436         else
437           j = 0;
438       }
439       else
440       {
441
442         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444         if (i > MSG_IN_QUEUE_SIZE - n)
445           i = MSG_IN_QUEUE_SIZE - n + 1;
446         i -= j;
447       }
448
449       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451       {
452         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453           msg->header.length, plci->msg_in_write_pos,
454           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456         return _QUEUE_FULL;
457       }
458       c = false;
459       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
460        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461       {
462         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463           c = true;
464       }
465       if (msg->header.command == _DATA_B3_R)
466       {
467         if (msg->header.length < 20)
468         {
469           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470           return _BAD_MSG;
471         }
472         ncci_ptr = &(a->ncci[ncci]);
473         n = ncci_ptr->data_pending;
474         l = ncci_ptr->data_ack_pending;
475         k = plci->msg_in_read_pos;
476         while (k != plci->msg_in_write_pos)
477         {
478           if (k == plci->msg_in_wrap_pos)
479             k = 0;
480           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482           {
483             n++;
484             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485               l++;
486           }
487
488           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
489             MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491         }
492         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493         {
494           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497           return _QUEUE_FULL;
498         }
499         if (plci->req_in || plci->internal_command)
500         {
501           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
502            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503           {
504             dbug(0,dprintf("Q-FULL3(requeue)"));
505
506             return _QUEUE_FULL;
507           }
508           c = true;
509         }
510       }
511       else
512       {
513         if (plci->req_in || plci->internal_command)
514           c = true;
515         else
516         {
517           plci->command = msg->header.command;
518           plci->number = msg->header.number;
519         }
520       }
521       if (c)
522       {
523         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524           msg->header.command, plci->req_in, plci->internal_command,
525           msg->header.length, plci->msg_in_write_pos,
526           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527         if (j == 0)
528           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
530         for (i = 0; i < msg->header.length; i++)
531           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
532         if (m->header.command == _DATA_B3_R)
533         {
534
535           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
536
537         }
538
539         j = (j + 3) & 0xfffc;
540
541         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
542         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543         return 0;
544       }
545     }
546     else
547     {
548       plci = NULL;
549     }
550   }
551   dbug(1,dprintf("com=%x",msg->header.command));
552
553   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554   for(i=0, ret = _BAD_MSG; 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 unsuccessfull
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 = (byte)(&(((T30_INFO *) 0)->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 = (byte)(((T30_INFO *) 0)->station_id + 20);
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 = (byte)(&(((T30_INFO *) 0)->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 = ((byte)(((T30_INFO *) 0)->station_id + 20));
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 = ((byte)(((T30_INFO *) 0)->station_id + 20));
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 < 20; 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 = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((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 + (-((int) 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 extention */
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<20; 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 = 20;
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[20])));
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             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8427             ((T30_INFO *)&nlc[1])->station_id[20 + 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                 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8435               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8436               ((T30_INFO *)&nlc[1])->station_id[20 + 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           ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
8448         }
8449       else
8450         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8451
8452       plci->nsf_control_bits = 0;
8453       if(plci->B3_prot == 5)
8454       {
8455         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8456          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8457         {
8458           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8459         }
8460         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8461          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8462         {
8463           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8464         }
8465         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8466           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8467         {
8468         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8469           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8470         {
8471           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8472           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8473             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8474           }
8475             len = nlc[0];
8476           pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8477    if (pos < plci->fax_connect_info_length)
8478    {
8479      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8480               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8481           }
8482    else
8483      nlc[++len] = 0;
8484    if (pos < plci->fax_connect_info_length)
8485    {
8486      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8487               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8488           }
8489    else
8490      nlc[++len] = 0;
8491           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8492             & (1L << PRIVATE_FAX_NONSTANDARD))
8493           {
8494      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8495      {
8496               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8497                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8498        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8499                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8500             }
8501      else
8502      {
8503               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8504               {
8505                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8506                 nlc[++len] = 0;
8507               }
8508        else
8509        {
8510                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8511                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8512          nlc[++len] = (byte)(b3_config_parms[4].length);
8513          for (i = 0; i < b3_config_parms[4].length; i++)
8514     nlc[++len] = b3_config_parms[4].info[1+i];
8515        }
8516             }
8517           }
8518             nlc[0] = len;
8519    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8520     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8521    {
8522             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8523           }
8524         }
8525       }
8526
8527       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8528       len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8529       for (i = 0; i < len; i++)
8530         plci->fax_connect_info_buffer[i] = nlc[1+i];
8531       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8532       i += ((T30_INFO *)&nlc[1])->head_line_len;
8533       while (i < nlc[0])
8534         plci->fax_connect_info_buffer[len++] = nlc[++i];
8535       plci->fax_connect_info_length = len;
8536     }
8537     else
8538     {
8539       nlc[0] = 14;
8540       if(b3_config->length!=16)
8541         return _B3_PARM_NOT_SUPPORTED;
8542       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8543       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8544         return _B3_PARM_NOT_SUPPORTED;
8545       nlc[13] = b3_config->info[13];
8546       if(GET_WORD(&b3_config->info[15])>=nlc[13])
8547         return _B3_PARM_NOT_SUPPORTED;
8548       nlc[14] = b3_config->info[15];
8549     }
8550   }
8551   else
8552   {
8553     if (plci->B3_prot == 4 
8554      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8555   }
8556   add_p(plci, NLC, nlc);
8557   return 0;
8558 }
8559
8560 /*----------------------------------------------------------------*/
8561 /*      make the same as add_b23, but only for the modem related  */
8562 /*      L2 and L3 B-Chan protocol.                                */
8563 /*                                                                */
8564 /*      Enabled L2 and L3 Configurations:                         */
8565 /*        If L1 == Modem all negotiation                          */
8566 /*          only L2 == Modem with full negotiation is allowed     */
8567 /*        If L1 == Modem async or sync                            */
8568 /*          only L2 == Transparent is allowed                     */
8569 /*        L3 == Modem or L3 == Transparent are allowed            */
8570 /*      B2 Configuration for modem:                               */
8571 /*          word : enable/disable compression, bitoptions         */
8572 /*      B3 Configuration for modem:                               */
8573 /*          empty                                                 */
8574 /*----------------------------------------------------------------*/
8575 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8576 {
8577   static byte lli[12] = {1,1};
8578   static byte llc[3] = {2,0,0};
8579   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8580     API_PARSE mdm_config[2];
8581   word i;
8582   word b2_config = 0;
8583
8584   for(i=0;i<2;i++) mdm_config[i].length = 0;
8585   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8586
8587   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8588     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8589    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8590     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8591   {
8592     return (_B_STACK_NOT_SUPPORTED);
8593   }
8594   if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8595    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8596   {
8597     return (_B_STACK_NOT_SUPPORTED);
8598   }
8599
8600   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8601   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8602
8603   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8604   {
8605     if (api_parse (&bp_parms[4].info[1],
8606                   (word)bp_parms[4].length, "w",
8607                   mdm_config))
8608     {
8609       return (_WRONG_MESSAGE_FORMAT);
8610     }
8611     b2_config = GET_WORD(mdm_config[0].info);
8612   }
8613
8614   /* OK, L2 is modem */
8615
8616   lli[0] = 1;
8617   lli[1] = 1;
8618   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8619     lli[1] |= 2;
8620   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8621     lli[1] |= 4;
8622
8623   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8624     lli[1] |= 0x10;
8625     if (plci->rx_dma_descriptor <= 0) {
8626       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8627       if (plci->rx_dma_descriptor >= 0)
8628         plci->rx_dma_descriptor++;
8629     }
8630     if (plci->rx_dma_descriptor > 0) {
8631       lli[1] |= 0x40;
8632       lli[0] = 6;
8633       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8634       lli[3] = (byte)plci->rx_dma_magic;
8635       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8636       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8637       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8638     }
8639   }
8640
8641   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8642     lli[1] |= 0x20;
8643   }
8644
8645   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8646     /*V42*/ 10 : /*V42_IN*/ 9;
8647   llc[2] = 4;                      /* pass L3 always transparent */
8648   add_p(plci, LLI, lli);
8649   add_p(plci, LLC, llc);
8650   i =  1;
8651   PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8652   i += 2;
8653   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8654   {
8655     if (bp_parms[4].length)
8656   {
8657     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8658     dlc[i++] = 3; /* Addr A */
8659     dlc[i++] = 1; /* Addr B */
8660     dlc[i++] = 7; /* modulo mode */
8661     dlc[i++] = 7; /* window size */
8662     dlc[i++] = 0; /* XID len Lo  */
8663     dlc[i++] = 0; /* XID len Hi  */
8664
8665     if (b2_config & MDM_B2_DISABLE_V42bis)
8666     {
8667       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8668     }
8669     if (b2_config & MDM_B2_DISABLE_MNP)
8670     {
8671       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8672     }
8673     if (b2_config & MDM_B2_DISABLE_TRANS)
8674     {
8675       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8676     }
8677     if (b2_config & MDM_B2_DISABLE_V42)
8678     {
8679       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8680     }
8681     if (b2_config & MDM_B2_DISABLE_COMP)
8682     {
8683       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8684     }
8685     i++;
8686   }
8687   }
8688   else
8689   {
8690     dlc[i++] = 3; /* Addr A */
8691     dlc[i++] = 1; /* Addr B */
8692     dlc[i++] = 7; /* modulo mode */
8693     dlc[i++] = 7; /* window size */
8694     dlc[i++] = 0; /* XID len Lo  */
8695     dlc[i++] = 0; /* XID len Hi  */
8696     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8697                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8698                DLC_MODEMPROT_DISABLE_V42_DETECT |
8699                DLC_MODEMPROT_DISABLE_COMPRESSION;
8700   }
8701   dlc[0] = (byte)(i - 1);
8702 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8703   add_p(plci, DLC, dlc);
8704   return (0);
8705 }
8706
8707
8708 /*------------------------------------------------------------------*/
8709 /* send a request for the signaling entity                          */
8710 /*------------------------------------------------------------------*/
8711
8712 static void sig_req(PLCI *plci, byte req, byte Id)
8713 {
8714   if(!plci) return;
8715   if(plci->adapter->adapter_disabled) return;
8716   dbug(1,dprintf("sig_req(%x)",req));
8717   if (req == REMOVE)
8718     plci->sig_remove_id = plci->Sig.Id;
8719   if(plci->req_in==plci->req_in_start) {
8720     plci->req_in +=2;
8721     plci->RBuffer[plci->req_in++] = 0;
8722   }
8723   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8724   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8725   plci->RBuffer[plci->req_in++] = req;  /* request */
8726   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8727   plci->req_in_start = plci->req_in;
8728 }
8729
8730 /*------------------------------------------------------------------*/
8731 /* send a request for the network layer entity                      */
8732 /*------------------------------------------------------------------*/
8733
8734 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8735 {
8736   if(!plci) return;
8737   if(plci->adapter->adapter_disabled) return;
8738   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8739   if (req == REMOVE)
8740   {
8741     plci->nl_remove_id = plci->NL.Id;
8742     ncci_remove (plci, 0, (byte)(ncci != 0));
8743     ncci = 0;
8744   }
8745   if(plci->req_in==plci->req_in_start) {
8746     plci->req_in +=2;
8747     plci->RBuffer[plci->req_in++] = 0;
8748   }
8749   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8750   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8751   plci->RBuffer[plci->req_in++] = req;  /* request */
8752   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8753   plci->req_in_start = plci->req_in;
8754 }
8755
8756 static void send_req(PLCI *plci)
8757 {
8758   ENTITY   * e;
8759   word l;
8760 /*  word i; */
8761
8762   if(!plci) return;
8763   if(plci->adapter->adapter_disabled) return;
8764   channel_xmit_xon (plci);
8765
8766         /* if nothing to do, return */
8767   if(plci->req_in==plci->req_out) return;
8768   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8769
8770   if(plci->nl_req || plci->sig_req) return;
8771
8772   l = GET_WORD(&plci->RBuffer[plci->req_out]);
8773   plci->req_out += 2;
8774   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8775   plci->req_out += l;
8776   if(plci->RBuffer[plci->req_out]==1)
8777   {
8778     e = &plci->NL;
8779     plci->req_out++;
8780     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8781     e->ReqCh = plci->RBuffer[plci->req_out++];
8782     if(!(e->Id & 0x1f))
8783     {
8784       e->Id = NL_ID;
8785       plci->RBuffer[plci->req_out-4] = CAI;
8786       plci->RBuffer[plci->req_out-3] = 1;
8787       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8788       plci->RBuffer[plci->req_out-1] = 0;
8789       l+=3;
8790       plci->nl_global_req = plci->nl_req;
8791     }
8792     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8793   }
8794   else
8795   {
8796     e = &plci->Sig;
8797     if(plci->RBuffer[plci->req_out])
8798       e->Id = plci->RBuffer[plci->req_out];
8799     plci->req_out++;
8800     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8801     e->ReqCh = plci->RBuffer[plci->req_out++];
8802     if(!(e->Id & 0x1f))
8803       plci->sig_global_req = plci->sig_req;
8804     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8805   }
8806   plci->XData[0].PLength = l;
8807   e->X = plci->XData;
8808   plci->adapter->request(e);
8809   dbug(1,dprintf("send_ok"));
8810 }
8811
8812 static void send_data(PLCI *plci)
8813 {
8814   DIVA_CAPI_ADAPTER   * a;
8815   DATA_B3_DESC   * data;
8816   NCCI   *ncci_ptr;
8817   word ncci;
8818
8819   if (!plci->nl_req && plci->ncci_ring_list)
8820   {
8821     a = plci->adapter;
8822     ncci = plci->ncci_ring_list;
8823     do
8824     {
8825       ncci = a->ncci_next[ncci];
8826       ncci_ptr = &(a->ncci[ncci]);
8827       if (!(a->ncci_ch[ncci]
8828          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8829       {
8830         if (ncci_ptr->data_pending)
8831         {
8832           if ((a->ncci_state[ncci] == CONNECTED)
8833            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8834            || (plci->send_disc == ncci))
8835           {
8836             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8837             if ((plci->B2_prot == B2_V120_ASYNC)
8838              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8839              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8840             {
8841               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8842               plci->NData[1].PLength = data->Length;
8843               if (data->Flags & 0x10)
8844                 plci->NData[0].P = v120_break_header;
8845               else
8846                 plci->NData[0].P = v120_default_header;
8847               plci->NData[0].PLength = 1 ;
8848               plci->NL.XNum = 2;
8849               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8850             }
8851             else
8852             {
8853               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8854               plci->NData[0].PLength = data->Length;
8855               if (data->Flags & 0x10)
8856                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8857
8858               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8859                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8860
8861               else
8862                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8863             }
8864             plci->NL.X = plci->NData;
8865             plci->NL.ReqCh = a->ncci_ch[ncci];
8866             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8867             plci->data_sent = true;
8868             plci->data_sent_ptr = data->P;
8869             a->request(&plci->NL);
8870           }
8871           else {
8872             cleanup_ncci_data (plci, ncci);
8873           }
8874         }
8875         else if (plci->send_disc == ncci)
8876         {
8877           /* dprintf("N_DISC"); */
8878           plci->NData[0].PLength = 0;
8879           plci->NL.ReqCh = a->ncci_ch[ncci];
8880           plci->NL.Req = plci->nl_req = N_DISC;
8881           a->request(&plci->NL);
8882           plci->command = _DISCONNECT_B3_R;
8883           plci->send_disc = 0;
8884         }
8885       }
8886     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8887     plci->ncci_ring_list = ncci;
8888   }
8889 }
8890
8891 static void listen_check(DIVA_CAPI_ADAPTER *a)
8892 {
8893   word i,j;
8894   PLCI   * plci;
8895   byte activnotifiedcalls = 0;
8896
8897   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8898   if (!remove_started && !a->adapter_disabled)
8899   {
8900     for(i=0;i<a->max_plci;i++)
8901     {
8902       plci = &(a->plci[i]);
8903       if(plci->notifiedcall) activnotifiedcalls++;
8904     }
8905     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8906
8907     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8908       if((j=get_plci(a))) {
8909         a->listen_active++;
8910         plci = &a->plci[j-1];
8911         plci->State = LISTENING;
8912
8913         add_p(plci,OAD,"\x01\xfd");
8914
8915         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8916
8917         add_p(plci,CAI,"\x01\xc0");
8918         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8919         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8920         add_p(plci,SHIFT|6,NULL);
8921         add_p(plci,SIN,"\x02\x00\x00");
8922         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8923         sig_req(plci,ASSIGN,DSIG_ID);
8924         send_req(plci);
8925       }
8926     }
8927   }
8928 }
8929
8930 /*------------------------------------------------------------------*/
8931 /* functions for all parameters sent in INDs                        */
8932 /*------------------------------------------------------------------*/
8933
8934 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8935 {
8936   word ploc;            /* points to current location within packet */
8937   byte w;
8938   byte wlen;
8939   byte codeset,lock;
8940   byte   * in;
8941   word i;
8942   word code;
8943   word mIEindex = 0;
8944   ploc = 0;
8945   codeset = 0;
8946   lock = 0;
8947
8948   in = plci->Sig.RBuffer->P;
8949   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8950   {                            /* element but parms array is larger      */
8951     parms[i] = (byte   *)"";
8952   }
8953   for(i=0; i<multiIEsize; i++)
8954   {
8955     parms[i] = (byte   *)"";
8956   }
8957
8958   while(ploc<plci->Sig.RBuffer->length-1) {
8959
8960         /* read information element id and length                   */
8961     w = in[ploc];
8962
8963     if(w & 0x80) {
8964 /*    w &=0xf0; removed, cannot detect congestion levels */
8965 /*    upper 4 bit masked with w==SHIFT now               */
8966       wlen = 0;
8967     }
8968     else {
8969       wlen = (byte)(in[ploc+1]+1);
8970     }
8971         /* check if length valid (not exceeding end of packet)      */
8972     if((ploc+wlen) > 270) return ;
8973     if(lock & 0x80) lock &=0x7f;
8974     else codeset = lock;
8975
8976     if((w&0xf0)==SHIFT) {
8977       codeset = in[ploc];
8978       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8979       codeset &=7;
8980       lock |=0x80;
8981     }
8982     else {
8983       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8984       else code = w;
8985       code |= (codeset<<8);
8986
8987       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8988
8989       if(i<parms_id[0]+1) {
8990         if(!multiIEsize) { /* with multiIEs use next field index,          */
8991           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8992         }
8993
8994         parms[mIEindex] = &in[ploc+1];
8995         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8996         if(parms_id[i]==OAD
8997         || parms_id[i]==CONN_NR
8998         || parms_id[i]==CAD) {
8999           if(in[ploc+2] &0x80) {
9000             in[ploc+0] = (byte)(in[ploc+1]+1);
9001             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
9002             in[ploc+2] = 0x80;
9003             parms[mIEindex] = &in[ploc];
9004           }
9005         }
9006         mIEindex++;       /* effects multiIEs only */
9007       }
9008     }
9009
9010     ploc +=(wlen+1);
9011   }
9012   return ;
9013 }
9014
9015 /*------------------------------------------------------------------*/
9016 /* try to match a cip from received BC and HLC                      */
9017 /*------------------------------------------------------------------*/
9018
9019 static byte ie_compare(byte *ie1, byte *ie2)
9020 {
9021   word i;
9022   if(!ie1 || ! ie2) return false;
9023   if(!ie1[0]) return false;
9024   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9025   return true;
9026 }
9027
9028 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9029 {
9030   word i;
9031   word j;
9032
9033   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9034
9035   for(j=16;j<29 &&
9036            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9037   if(j==29) return i;
9038   return j;
9039 }
9040
9041
9042 static byte AddInfo(byte   **add_i,
9043                     byte   **fty_i,
9044                     byte   *esc_chi,
9045                     byte *facility)
9046 {
9047   byte i;
9048   byte j;
9049   byte k;
9050   byte flen;
9051   byte len=0;
9052    /* facility is a nested structure */
9053    /* FTY can be more than once      */
9054
9055         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9056   {
9057     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9058   }
9059
9060   else
9061   {
9062     add_i[0] = (byte   *)"";
9063   }
9064   if(!fty_i[0][0])
9065   {
9066     add_i[3] = (byte   *)"";
9067   }
9068   else
9069   {    /* facility array found  */
9070     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9071     {
9072       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9073       len += fty_i[i][0];
9074       len += 2;
9075       flen=fty_i[i][0];
9076       facility[j++]=0x1c; /* copy fac IE */
9077       for(k=0;k<=flen;k++,j++)
9078       {
9079         facility[j]=fty_i[i][k];
9080 /*      dbug(1,dprintf("%x ",facility[j])); */
9081       }
9082     }
9083     facility[0] = len;
9084     add_i[3] = facility;
9085   }
9086 /*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9087   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9088   len += 4;                          /* calculate length of all */
9089   return(len);
9090 }
9091
9092 /*------------------------------------------------------------------*/
9093 /* voice and codec features                                         */
9094 /*------------------------------------------------------------------*/
9095
9096 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9097 {
9098   byte voice_chi[] = "\x02\x18\x01";
9099   byte channel;
9100
9101   channel = chi[chi[0]]&0x3;
9102   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9103   voice_chi[2] = (channel) ? channel : 1;
9104   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9105   add_p(plci,ESC,voice_chi);                  /* Channel */
9106   sig_req(plci,TEL_CTRL,0);
9107   send_req(plci);
9108   if(a->AdvSignalPLCI)
9109   {
9110     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9111   }
9112 }
9113
9114 static void VoiceChannelOff(PLCI *plci)
9115 {
9116   dbug(1,dprintf("ExtDevOFF"));
9117   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9118   sig_req(plci,TEL_CTRL,0);
9119   send_req(plci);
9120   if(plci->adapter->AdvSignalPLCI)
9121   {
9122     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9123   }
9124 }
9125
9126
9127 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9128                             byte hook_listen)
9129 {
9130   word j;
9131   PLCI   *splci;
9132
9133   /* check if hardware supports handset with hook states (adv.codec) */
9134   /* or if just a on board codec is supported                        */
9135   /* the advanced codec plci is just for internal use                */
9136
9137   /* diva Pro with on-board codec:                                   */
9138   if(a->profile.Global_Options & HANDSET)
9139   {
9140     /* new call, but hook states are already signalled */
9141     if(a->AdvCodecFLAG)
9142     {
9143       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9144       {
9145         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9146         return 0x2001; /* codec in use by another application */
9147       }
9148       if(plci!=NULL)
9149       {
9150         a->AdvSignalPLCI = plci;
9151         plci->tel=ADV_VOICE;
9152       }
9153       return 0;                      /* adv codec still used */
9154     }
9155     if((j=get_plci(a)))
9156     {
9157       splci = &a->plci[j-1];
9158       splci->tel = CODEC_PERMANENT;
9159       /* hook_listen indicates if a facility_req with handset/hook support */
9160       /* was sent. Otherwise if just a call on an external device was made */
9161       /* the codec will be used but the hook info will be discarded (just  */
9162       /* the external controller is in use                                 */
9163       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9164       else
9165       {
9166         splci->State = ADVANCED_VOICE_NOSIG;
9167         if(plci)
9168         {
9169           plci->spoofed_msg = SPOOFING_REQUIRED;
9170         }
9171                                                /* indicate D-ch connect if  */
9172       }                                        /* codec is connected OK     */
9173       if(plci!=NULL)
9174       {
9175         a->AdvSignalPLCI = plci;
9176         plci->tel=ADV_VOICE;
9177       }
9178       a->AdvSignalAppl = appl;
9179       a->AdvCodecFLAG = true;
9180       a->AdvCodecPLCI = splci;
9181       add_p(splci,CAI,"\x01\x15");
9182       add_p(splci,LLI,"\x01\x00");
9183       add_p(splci,ESC,"\x02\x18\x00");
9184       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9185       splci->internal_command = PERM_COD_ASSIGN;
9186       dbug(1,dprintf("Codec Assign"));
9187       sig_req(splci,ASSIGN,DSIG_ID);
9188       send_req(splci);
9189     }
9190     else
9191     {
9192       return 0x2001; /* wrong state, no more plcis */
9193     }
9194   }
9195   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9196   {
9197     if(hook_listen) return 0x300B;               /* Facility not supported */
9198                                                  /* no hook with SCOM      */
9199     if(plci!=NULL) plci->tel = CODEC;
9200     dbug(1,dprintf("S/SCOM codec"));
9201     /* first time we use the scom-s codec we must shut down the internal   */
9202     /* handset application of the card. This can be done by an assign with */
9203     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9204     if(!a->scom_appl_disable){
9205       if((j=get_plci(a))) {
9206         splci = &a->plci[j-1];
9207         add_p(splci,CAI,"\x01\x80");
9208         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9209         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9210         send_req(splci);
9211         a->scom_appl_disable = true;
9212       }
9213       else{
9214         return 0x2001; /* wrong state, no more plcis */
9215       }
9216     }
9217   }
9218   else return 0x300B;               /* Facility not supported */
9219
9220   return 0;
9221 }
9222
9223
9224 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9225 {
9226
9227   dbug(1,dprintf("CodecIdCheck"));
9228
9229   if(a->AdvSignalPLCI == plci)
9230   {
9231     dbug(1,dprintf("PLCI owns codec"));
9232     VoiceChannelOff(a->AdvCodecPLCI);
9233     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9234     {
9235       dbug(1,dprintf("remove temp codec PLCI"));
9236       plci_remove(a->AdvCodecPLCI);
9237       a->AdvCodecFLAG  = 0;
9238       a->AdvCodecPLCI  = NULL;
9239       a->AdvSignalAppl = NULL;
9240     }
9241     a->AdvSignalPLCI = NULL;
9242   }
9243 }
9244
9245 /* -------------------------------------------------------------------
9246     Ask for physical address of card on PCI bus
9247    ------------------------------------------------------------------- */
9248 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9249                                         IDI_SYNC_REQ  * preq) {
9250   a->sdram_bar = 0;
9251   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9252     ENTITY   * e = (ENTITY   *)preq;
9253
9254     e->user[0] = a->Id - 1;
9255     preq->xdi_sdram_bar.info.bar    = 0;
9256     preq->xdi_sdram_bar.Req         = 0;
9257     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9258
9259     (*(a->request))(e);
9260
9261     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9262     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9263   }
9264 }
9265
9266 /* -------------------------------------------------------------------
9267      Ask XDI about extended features
9268    ------------------------------------------------------------------- */
9269 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9270   IDI_SYNC_REQ   * preq;
9271     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9272
9273     char features[4];
9274   preq = (IDI_SYNC_REQ   *)&buffer[0];
9275
9276   if (!diva_xdi_extended_features) {
9277     ENTITY   * e = (ENTITY   *)preq;
9278     diva_xdi_extended_features |= 0x80000000;
9279
9280     e->user[0] = a->Id - 1;
9281     preq->xdi_extended_features.Req = 0;
9282     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9283     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9284     preq->xdi_extended_features.info.features = &features[0];
9285
9286     (*(a->request))(e);
9287
9288     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9289       /*
9290          Check features located in the byte '0'
9291          */
9292       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9293         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9294       }
9295       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9296         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9297         dbug(1,dprintf("XDI provides RxDMA"));
9298       }
9299       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9300         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9301       }
9302       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9303         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9304         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9305       }
9306
9307     }
9308   }
9309
9310   diva_ask_for_xdi_sdram_bar (a, preq);
9311 }
9312
9313 /*------------------------------------------------------------------*/
9314 /* automatic law                                                    */
9315 /*------------------------------------------------------------------*/
9316 /* called from OS specific part after init time to get the Law              */
9317 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9318 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9319 {
9320   word j;
9321   PLCI   *splci;
9322
9323   if(a->automatic_law) {
9324     return;
9325   }
9326   if((j=get_plci(a))) {
9327     diva_get_extended_adapter_features (a);
9328     splci = &a->plci[j-1];
9329     a->automatic_lawPLCI = splci;
9330     a->automatic_law = 1;
9331     add_p(splci,CAI,"\x01\x80");
9332     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9333     splci->internal_command = USELAW_REQ;
9334     splci->command = 0;
9335     splci->number = 0;
9336     sig_req(splci,ASSIGN,DSIG_ID);
9337     send_req(splci);
9338   }
9339 }
9340
9341 /* called from OS specific part if an application sends an Capi20Release */
9342 word CapiRelease(word Id)
9343 {
9344   word i, j, appls_found;
9345   PLCI   *plci;
9346   APPL   *this;
9347   DIVA_CAPI_ADAPTER   *a;
9348
9349   if (!Id)
9350   {
9351     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9352     return (_WRONG_APPL_ID);
9353   }
9354
9355   this = &application[Id-1];               /* get application pointer */
9356
9357   for(i=0,appls_found=0; i<max_appl; i++)
9358   {
9359     if(application[i].Id)       /* an application has been found        */
9360     {
9361       appls_found++;
9362     }
9363   }
9364
9365   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9366   {
9367     a = &adapter[i];
9368     if (a->request)
9369     {
9370       a->Info_Mask[Id-1] = 0;
9371       a->CIP_Mask[Id-1] = 0;
9372       a->Notification_Mask[Id-1] = 0;
9373       a->codec_listen[Id-1] = NULL;
9374       a->requested_options_table[Id-1] = 0;
9375       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9376       {                                      /* with this application   */
9377         plci = &a->plci[j];
9378         if(plci->Id)                         /* if plci owns no application */
9379         {                                    /* it may be not jet connected */
9380           if(plci->State==INC_CON_PENDING
9381           || plci->State==INC_CON_ALERT)
9382           {
9383             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9384             {
9385               clear_c_ind_mask_bit (plci, (word)(Id-1));
9386               if(c_ind_mask_empty (plci))
9387               {
9388                 sig_req(plci,HANGUP,0);
9389                 send_req(plci);
9390                 plci->State = OUTG_DIS_PENDING;
9391               }
9392             }
9393           }
9394           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9395           {
9396             clear_c_ind_mask_bit (plci, (word)(Id-1));
9397             if(c_ind_mask_empty (plci))
9398             {
9399               if(!plci->appl)
9400               {
9401                 plci_remove(plci);
9402                 plci->State = IDLE;
9403               }
9404             }
9405           }
9406           if(plci->appl==this)
9407           {
9408             plci->appl = NULL;
9409             plci_remove(plci);
9410             plci->State = IDLE;
9411           }
9412         }
9413       }
9414       listen_check(a);
9415
9416       if(a->flag_dynamic_l1_down)
9417       {
9418         if(appls_found==1)            /* last application does a capi release */
9419         {
9420           if((j=get_plci(a)))
9421           {
9422             plci = &a->plci[j-1];
9423             plci->command = 0;
9424             add_p(plci,OAD,"\x01\xfd");
9425             add_p(plci,CAI,"\x01\x80");
9426             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9427             add_p(plci,SHIFT|6,NULL);
9428             add_p(plci,SIN,"\x02\x00\x00");
9429             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9430             sig_req(plci,ASSIGN,DSIG_ID);
9431             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9432             sig_req(plci,SIG_CTRL,0);
9433             send_req(plci);
9434           }
9435         }
9436       }
9437       if(a->AdvSignalAppl==this)
9438       {
9439         this->NullCREnable = false;
9440         if (a->AdvCodecPLCI)
9441         {
9442           plci_remove(a->AdvCodecPLCI);
9443           a->AdvCodecPLCI->tel = 0;
9444           a->AdvCodecPLCI->adv_nl = 0;
9445         }
9446         a->AdvSignalAppl = NULL;
9447         a->AdvSignalPLCI = NULL;
9448         a->AdvCodecFLAG = 0;
9449         a->AdvCodecPLCI = NULL;
9450       }
9451     }
9452   }
9453
9454   this->Id = 0;
9455
9456   return GOOD;
9457 }
9458
9459 static word plci_remove_check(PLCI   *plci)
9460 {
9461   if(!plci) return true;
9462   if(!plci->NL.Id && c_ind_mask_empty (plci))
9463   {
9464     if(plci->Sig.Id == 0xff)
9465       plci->Sig.Id = 0;
9466     if(!plci->Sig.Id)
9467     {
9468       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9469       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9470       if (plci->Id)
9471       {
9472         CodecIdCheck(plci->adapter, plci);
9473         clear_b1_config (plci);
9474         ncci_remove (plci, 0, false);
9475         plci_free_msg_in_queue (plci);
9476         channel_flow_control_remove (plci);
9477         plci->Id = 0;
9478         plci->State = IDLE;
9479         plci->channels = 0;
9480         plci->appl = NULL;
9481         plci->notifiedcall = 0;
9482       }
9483       listen_check(plci->adapter);
9484       return true;
9485     }
9486   }
9487   return false;
9488 }
9489
9490
9491 /*------------------------------------------------------------------*/
9492
9493 static byte plci_nl_busy (PLCI   *plci)
9494 {
9495   /* only applicable for non-multiplexed protocols */
9496   return (plci->nl_req
9497     || (plci->ncci_ring_list
9498      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9499      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9500 }
9501
9502
9503 /*------------------------------------------------------------------*/
9504 /* DTMF facilities                                                  */
9505 /*------------------------------------------------------------------*/
9506
9507
9508 static struct
9509 {
9510   byte send_mask;
9511   byte listen_mask;
9512   byte character;
9513   byte code;
9514 } dtmf_digit_map[] =
9515 {
9516   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9517   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9518   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9519   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9520   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9521   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9522   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9523   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9524   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9525   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9526   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9527   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9528   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9529   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9530   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9531   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9532   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9533   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9534   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9535   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9536
9537   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9538   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9539   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9540   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9541   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9542   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9543   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9544   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9545   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9546   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9547   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9548   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9549   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9550   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9551   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9552   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9553   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9554   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9555   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9556   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9557   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9558   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9559   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9560   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9561   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9562   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9563   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9564   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9565   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9566   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9567   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9568   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9569   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9570   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9571   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9572   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9573   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9574   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9575   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9576   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9577   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9578   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9579   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9580   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9581   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9582   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9583   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9584   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9585   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9586   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9587   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9588   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9589
9590 };
9591
9592 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9593
9594
9595 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9596 {
9597   word min_digit_duration, min_gap_duration;
9598
9599   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9600     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9601     (char   *)(FILE_), __LINE__, enable_mask));
9602
9603   if (enable_mask != 0)
9604   {
9605     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9606     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9607     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9608     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9609     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9610     plci->NData[0].PLength = 5;
9611
9612     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9613     plci->NData[0].PLength += 2;
9614     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9615
9616   }
9617   else
9618   {
9619     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9620     plci->NData[0].PLength = 1;
9621
9622     capidtmf_recv_disable (&(plci->capidtmf_state));
9623
9624   }
9625   plci->NData[0].P = plci->internal_req_buffer;
9626   plci->NL.X = plci->NData;
9627   plci->NL.ReqCh = 0;
9628   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9629   plci->adapter->request (&plci->NL);
9630 }
9631
9632
9633 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9634 {
9635   word w, i;
9636
9637   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9638     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9639     (char   *)(FILE_), __LINE__, digit_count));
9640
9641   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9642   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9643   PUT_WORD (&plci->internal_req_buffer[1], w);
9644   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9645   PUT_WORD (&plci->internal_req_buffer[3], w);
9646   for (i = 0; i < digit_count; i++)
9647   {
9648     w = 0;
9649     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9650       && (digit_buffer[i] != dtmf_digit_map[w].character))
9651     {
9652       w++;
9653     }
9654     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9655       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9656   }
9657   plci->NData[0].PLength = 5 + digit_count;
9658   plci->NData[0].P = plci->internal_req_buffer;
9659   plci->NL.X = plci->NData;
9660   plci->NL.ReqCh = 0;
9661   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9662   plci->adapter->request (&plci->NL);
9663 }
9664
9665
9666 static void dtmf_rec_clear_config (PLCI   *plci)
9667 {
9668
9669   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9670     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9671     (char   *)(FILE_), __LINE__));
9672
9673   plci->dtmf_rec_active = 0;
9674   plci->dtmf_rec_pulse_ms = 0;
9675   plci->dtmf_rec_pause_ms = 0;
9676
9677   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9678
9679 }
9680
9681
9682 static void dtmf_send_clear_config (PLCI   *plci)
9683 {
9684
9685   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9686     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9687     (char   *)(FILE_), __LINE__));
9688
9689   plci->dtmf_send_requests = 0;
9690   plci->dtmf_send_pulse_ms = 0;
9691   plci->dtmf_send_pause_ms = 0;
9692 }
9693
9694
9695 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9696 {
9697
9698   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9699     UnMapId (Id), (char   *)(FILE_), __LINE__));
9700
9701   while (plci->dtmf_send_requests != 0)
9702     dtmf_confirmation (Id, plci);
9703 }
9704
9705
9706 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9707 {
9708
9709   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9710     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9711
9712   return (GOOD);
9713 }
9714
9715
9716 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9717 {
9718   word Info;
9719
9720   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9721     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9722
9723   Info = GOOD;
9724   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9725   {
9726     switch (plci->adjust_b_state)
9727     {
9728     case ADJUST_B_RESTORE_DTMF_1:
9729       plci->internal_command = plci->adjust_b_command;
9730       if (plci_nl_busy (plci))
9731       {
9732         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9733         break;
9734       }
9735       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9736       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9737       break;
9738     case ADJUST_B_RESTORE_DTMF_2:
9739       if ((Rc != OK) && (Rc != OK_FC))
9740       {
9741         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9742           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9743         Info = _WRONG_STATE;
9744         break;
9745       }
9746       break;
9747     }
9748   }
9749   return (Info);
9750 }
9751
9752
9753 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9754 {
9755   word internal_command, Info;
9756   byte mask;
9757     byte result[4];
9758
9759   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9760     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9761     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9762     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9763
9764   Info = GOOD;
9765   result[0] = 2;
9766   PUT_WORD (&result[1], DTMF_SUCCESS);
9767   internal_command = plci->internal_command;
9768   plci->internal_command = 0;
9769   mask = 0x01;
9770   switch (plci->dtmf_cmd)
9771   {
9772
9773   case DTMF_LISTEN_TONE_START:
9774     mask <<= 1;
9775   case DTMF_LISTEN_MF_START:
9776     mask <<= 1;
9777
9778   case DTMF_LISTEN_START:
9779     switch (internal_command)
9780     {
9781     default:
9782       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9783         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9784     case DTMF_COMMAND_1:
9785       if (adjust_b_process (Id, plci, Rc) != GOOD)
9786       {
9787         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9788           UnMapId (Id), (char   *)(FILE_), __LINE__));
9789         Info = _FACILITY_NOT_SUPPORTED;
9790         break;
9791       }
9792       if (plci->internal_command)
9793         return;
9794     case DTMF_COMMAND_2:
9795       if (plci_nl_busy (plci))
9796       {
9797         plci->internal_command = DTMF_COMMAND_2;
9798         return;
9799       }
9800       plci->internal_command = DTMF_COMMAND_3;
9801       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9802       return;
9803     case DTMF_COMMAND_3:
9804       if ((Rc != OK) && (Rc != OK_FC))
9805       {
9806         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9807           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9808         Info = _FACILITY_NOT_SUPPORTED;
9809         break;
9810       }
9811
9812       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9813
9814       plci->dtmf_rec_active |= mask;
9815       break;
9816     }
9817     break;
9818
9819
9820   case DTMF_LISTEN_TONE_STOP:
9821     mask <<= 1;
9822   case DTMF_LISTEN_MF_STOP:
9823     mask <<= 1;
9824
9825   case DTMF_LISTEN_STOP:
9826     switch (internal_command)
9827     {
9828     default:
9829       plci->dtmf_rec_active &= ~mask;
9830       if (plci->dtmf_rec_active)
9831         break;
9832 /*
9833     case DTMF_COMMAND_1:
9834       if (plci->dtmf_rec_active)
9835       {
9836         if (plci_nl_busy (plci))
9837         {
9838           plci->internal_command = DTMF_COMMAND_1;
9839           return;
9840         }
9841         plci->dtmf_rec_active &= ~mask;
9842         plci->internal_command = DTMF_COMMAND_2;
9843         dtmf_enable_receiver (plci, false);
9844         return;
9845       }
9846       Rc = OK;
9847     case DTMF_COMMAND_2:
9848       if ((Rc != OK) && (Rc != OK_FC))
9849       {
9850         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9851           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9852         Info = _FACILITY_NOT_SUPPORTED;
9853         break;
9854       }
9855 */
9856       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9857         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9858     case DTMF_COMMAND_3:
9859       if (adjust_b_process (Id, plci, Rc) != GOOD)
9860       {
9861         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9862           UnMapId (Id), (char   *)(FILE_), __LINE__));
9863         Info = _FACILITY_NOT_SUPPORTED;
9864         break;
9865       }
9866       if (plci->internal_command)
9867         return;
9868       break;
9869     }
9870     break;
9871
9872
9873   case DTMF_SEND_TONE:
9874     mask <<= 1;
9875   case DTMF_SEND_MF:
9876     mask <<= 1;
9877
9878   case DTMF_DIGITS_SEND:
9879     switch (internal_command)
9880     {
9881     default:
9882       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9883         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9884         DTMF_COMMAND_1);
9885     case DTMF_COMMAND_1:
9886       if (adjust_b_process (Id, plci, Rc) != GOOD)
9887       {
9888         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9889           UnMapId (Id), (char   *)(FILE_), __LINE__));
9890         Info = _FACILITY_NOT_SUPPORTED;
9891         break;
9892       }
9893       if (plci->internal_command)
9894         return;
9895     case DTMF_COMMAND_2:
9896       if (plci_nl_busy (plci))
9897       {
9898         plci->internal_command = DTMF_COMMAND_2;
9899         return;
9900       }
9901       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9902       plci->internal_command = DTMF_COMMAND_3;
9903       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9904       return;
9905     case DTMF_COMMAND_3:
9906       if ((Rc != OK) && (Rc != OK_FC))
9907       {
9908         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9909           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9910         if (plci->dtmf_send_requests != 0)
9911           (plci->dtmf_send_requests)--;
9912         Info = _FACILITY_NOT_SUPPORTED;
9913         break;
9914       }
9915       return;
9916     }
9917     break;
9918   }
9919   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9920     "wws", Info, SELECTOR_DTMF, result);
9921 }
9922
9923
9924 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9925 {
9926   word Info;
9927   word i, j;
9928   byte mask;
9929     API_PARSE dtmf_parms[5];
9930     byte result[40];
9931
9932   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9933     UnMapId (Id), (char   *)(FILE_), __LINE__));
9934
9935   Info = GOOD;
9936   result[0] = 2;
9937   PUT_WORD (&result[1], DTMF_SUCCESS);
9938   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9939   {
9940     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9941       UnMapId (Id), (char   *)(FILE_), __LINE__));
9942     Info = _FACILITY_NOT_SUPPORTED;
9943   }
9944   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9945   {
9946     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9947       UnMapId (Id), (char   *)(FILE_), __LINE__));
9948     Info = _WRONG_MESSAGE_FORMAT;
9949   }
9950
9951   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9952     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9953   {
9954     if (!((a->requested_options_table[appl->Id-1])
9955         & (1L << PRIVATE_DTMF_TONE)))
9956     {
9957       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9958         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9959       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9960     }
9961     else
9962     {
9963       for (i = 0; i < 32; i++)
9964         result[4 + i] = 0;
9965       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9966       {
9967         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9968         {
9969           if (dtmf_digit_map[i].listen_mask != 0)
9970             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9971         }
9972       }
9973       else
9974       {
9975         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9976         {
9977           if (dtmf_digit_map[i].send_mask != 0)
9978             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9979         }
9980       }
9981       result[0] = 3 + 32;
9982       result[3] = 32;
9983     }
9984   }
9985
9986   else if (plci == NULL)
9987   {
9988     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9989       UnMapId (Id), (char   *)(FILE_), __LINE__));
9990     Info = _WRONG_IDENTIFIER;
9991   }
9992   else
9993   {
9994     if (!plci->State
9995      || !plci->NL.Id || plci->nl_remove_id)
9996     {
9997       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9998         UnMapId (Id), (char   *)(FILE_), __LINE__));
9999       Info = _WRONG_STATE;
10000     }
10001     else
10002     {
10003       plci->command = 0;
10004       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
10005       mask = 0x01;
10006       switch (plci->dtmf_cmd)
10007       {
10008
10009       case DTMF_LISTEN_TONE_START:
10010       case DTMF_LISTEN_TONE_STOP:
10011         mask <<= 1;
10012       case DTMF_LISTEN_MF_START:
10013       case DTMF_LISTEN_MF_STOP:
10014         mask <<= 1;
10015         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10016           & (1L << PRIVATE_DTMF_TONE)))
10017         {
10018           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10019             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10020           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10021           break;
10022         }
10023
10024       case DTMF_LISTEN_START:
10025       case DTMF_LISTEN_STOP:
10026         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10027          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10028         {
10029           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10030             UnMapId (Id), (char   *)(FILE_), __LINE__));
10031           Info = _FACILITY_NOT_SUPPORTED;
10032           break;
10033         }
10034         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10035         {
10036           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10037           {
10038             plci->dtmf_rec_pulse_ms = 0;
10039             plci->dtmf_rec_pause_ms = 0;
10040           }
10041           else
10042           {
10043             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10044             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10045           }
10046         }
10047         start_internal_command (Id, plci, dtmf_command);
10048         return (false);
10049
10050
10051       case DTMF_SEND_TONE:
10052         mask <<= 1;
10053       case DTMF_SEND_MF:
10054         mask <<= 1;
10055         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10056           & (1L << PRIVATE_DTMF_TONE)))
10057         {
10058           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10059             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10060           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10061           break;
10062         }
10063
10064       case DTMF_DIGITS_SEND:
10065         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10066         {
10067           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10068             UnMapId (Id), (char   *)(FILE_), __LINE__));
10069           Info = _WRONG_MESSAGE_FORMAT;
10070           break;
10071         }
10072         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10073         {
10074           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10075           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10076         }
10077         i = 0;
10078         j = 0;
10079         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10080         {
10081           j = 0;
10082           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10083             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10084              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10085           {
10086             j++;
10087           }
10088           i++;
10089         }
10090         if (j == DTMF_DIGIT_MAP_ENTRIES)
10091         {
10092           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10093             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10094           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10095           break;
10096         }
10097         if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10098         {
10099           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10100             UnMapId (Id), (char   *)(FILE_), __LINE__));
10101           Info = _WRONG_STATE;
10102           break;
10103         }
10104         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10105         start_internal_command (Id, plci, dtmf_command);
10106         return (false);
10107
10108       default:
10109         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10110           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10111         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10112       }
10113     }
10114   }
10115   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10116     "wws", Info, SELECTOR_DTMF, result);
10117   return (false);
10118 }
10119
10120
10121 static void dtmf_confirmation (dword Id, PLCI   *plci)
10122 {
10123   word Info;
10124   word i;
10125     byte result[4];
10126
10127   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10128     UnMapId (Id), (char   *)(FILE_), __LINE__));
10129
10130   Info = GOOD;
10131   result[0] = 2;
10132   PUT_WORD (&result[1], DTMF_SUCCESS);
10133   if (plci->dtmf_send_requests != 0)
10134   {
10135     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10136       "wws", GOOD, SELECTOR_DTMF, result);
10137     (plci->dtmf_send_requests)--;
10138     for (i = 0; i < plci->dtmf_send_requests; i++)
10139       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10140   }
10141 }
10142
10143
10144 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10145 {
10146   word i, j, n;
10147
10148   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10149     UnMapId (Id), (char   *)(FILE_), __LINE__));
10150
10151   n = 0;
10152   for (i = 1; i < length; i++)
10153   {
10154     j = 0;
10155     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10156       && ((msg[i] != dtmf_digit_map[j].code)
10157        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10158     {
10159       j++;
10160     }
10161     if (j < DTMF_DIGIT_MAP_ENTRIES)
10162     {
10163
10164       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10165        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10166        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10167       {
10168         if (n + 1 == i)
10169         {
10170           for (i = length; i > n + 1; i--)
10171             msg[i] = msg[i - 1];
10172           length++;
10173           i++;
10174         }
10175         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10176       }
10177       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10178
10179       msg[++n] = dtmf_digit_map[j].character;
10180     }
10181   }
10182   if (n != 0)
10183   {
10184     msg[0] = (byte) n;
10185     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10186   }
10187 }
10188
10189
10190 /*------------------------------------------------------------------*/
10191 /* DTMF parameters                                                  */
10192 /*------------------------------------------------------------------*/
10193
10194 static void dtmf_parameter_write (PLCI   *plci)
10195 {
10196   word i;
10197     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10198
10199   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10200     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10201     (char   *)(FILE_), __LINE__));
10202
10203   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10204   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10205   for (i = 0; i < plci->dtmf_parameter_length; i++)
10206     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10207   add_p (plci, FTY, parameter_buffer);
10208   sig_req (plci, TEL_CTRL, 0);
10209   send_req (plci);
10210 }
10211
10212
10213 static void dtmf_parameter_clear_config (PLCI   *plci)
10214 {
10215
10216   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10217     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10218     (char   *)(FILE_), __LINE__));
10219
10220   plci->dtmf_parameter_length = 0;
10221 }
10222
10223
10224 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10225 {
10226
10227   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10228     UnMapId (Id), (char   *)(FILE_), __LINE__));
10229
10230 }
10231
10232
10233 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10234 {
10235
10236   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10237     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10238
10239   return (GOOD);
10240 }
10241
10242
10243 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10244 {
10245   word Info;
10246
10247   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10248     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10249
10250   Info = GOOD;
10251   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10252    && (plci->dtmf_parameter_length != 0))
10253   {
10254     switch (plci->adjust_b_state)
10255     {
10256     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10257       plci->internal_command = plci->adjust_b_command;
10258       if (plci->sig_req)
10259       {
10260         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10261         break;
10262       }
10263       dtmf_parameter_write (plci);
10264       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10265       break;
10266     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10267       if ((Rc != OK) && (Rc != OK_FC))
10268       {
10269         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10270           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10271         Info = _WRONG_STATE;
10272         break;
10273       }
10274       break;
10275     }
10276   }
10277   return (Info);
10278 }
10279
10280
10281 /*------------------------------------------------------------------*/
10282 /* Line interconnect facilities                                     */
10283 /*------------------------------------------------------------------*/
10284
10285
10286 LI_CONFIG   *li_config_table;
10287 word li_total_channels;
10288
10289
10290 /*------------------------------------------------------------------*/
10291 /* translate a CHI information element to a channel number          */
10292 /* returns 0xff - any channel                                       */
10293 /*         0xfe - chi wrong coding                                  */
10294 /*         0xfd - D-channel                                         */
10295 /*         0x00 - no channel                                        */
10296 /*         else channel number / PRI: timeslot                      */
10297 /* if channels is provided we accept more than one channel.         */
10298 /*------------------------------------------------------------------*/
10299
10300 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10301 {
10302   int p;
10303   int i;
10304   dword map;
10305   byte excl;
10306   byte ofs;
10307   byte ch;
10308
10309   if (pchannelmap) *pchannelmap = 0;
10310   if(!chi[0]) return 0xff;
10311   excl = 0;
10312
10313   if(chi[1] & 0x20) {
10314     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10315     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10316     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10317     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10318     if(chi[1] &0x08) excl = 0x40;
10319
10320         /* int. id present */
10321     if(chi[1] &0x40) {
10322       p=i+1;
10323       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10324       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10325     }
10326
10327         /* coding standard, Number/Map, Channel Type */
10328     p=i+1;
10329     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10330     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10331     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10332
10333         /* Number/Map */
10334     if(chi[p] &0x10) {
10335
10336         /* map */
10337       if((chi[0]-p)==4) ofs = 0;
10338       else if((chi[0]-p)==3) ofs = 1;
10339       else return 0xfe;
10340       ch = 0;
10341       map = 0;
10342       for(i=0; i<4 && p<chi[0]; i++) {
10343         p++;
10344         ch += 8;
10345         map <<= 8;
10346         if(chi[p]) {
10347           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10348           map |= chi[p];
10349         }
10350       }
10351       ch += ofs;
10352       map <<= ofs;
10353     }
10354     else {
10355
10356         /* number */
10357       p=i+1;
10358       ch = chi[p] &0x3f;
10359       if(pchannelmap) {
10360         if((byte)(chi[0]-p)>30) return 0xfe;
10361         map = 0;
10362         for(i=p; i<=chi[0]; i++) {
10363           if ((chi[i] &0x7f) > 31) return 0xfe;
10364           map |= (1L << (chi[i] &0x7f));
10365         }
10366       }
10367       else {
10368         if(p!=chi[0]) return 0xfe;
10369         if (ch > 31) return 0xfe;
10370         map = (1L << ch);
10371       }
10372       if(chi[p] &0x40) return 0xfe;
10373     }
10374     if (pchannelmap) *pchannelmap = map;
10375     else if (map != ((dword)(1L << ch))) return 0xfe;
10376     return (byte)(excl | ch);
10377   }
10378   else {  /* not PRI */
10379     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10380     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10381     if(chi[1] &0x08) excl = 0x40;
10382
10383     switch(chi[1] |0x98) {
10384     case 0x98: return 0;
10385     case 0x99:
10386       if (pchannelmap) *pchannelmap = 2;
10387       return excl |1;
10388     case 0x9a:
10389       if (pchannelmap) *pchannelmap = 4;
10390       return excl |2;
10391     case 0x9b: return 0xff;
10392     case 0x9c: return 0xfd; /* d-ch */
10393     default: return 0xfe;
10394     }
10395   }
10396 }
10397
10398
10399 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10400 {
10401   DIVA_CAPI_ADAPTER   *a;
10402   PLCI   *splci;
10403   byte old_id;
10404
10405   a = plci->adapter;
10406   old_id = plci->li_bchannel_id;
10407   if (a->li_pri)
10408   {
10409     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10410       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10411     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10412     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10413       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10414   }
10415   else
10416   {
10417     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10418     {
10419       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10420         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10421       plci->li_bchannel_id = bchannel_id & 0x03;
10422       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10423       {
10424         splci = a->AdvSignalPLCI;
10425         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10426         {
10427           if ((splci->li_bchannel_id != 0)
10428            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10429           {
10430             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10431           }
10432           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10433           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10434           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10435             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10436             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10437         }
10438       }
10439       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10440         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10441     }
10442   }
10443   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10444    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10445   {
10446     mixer_clear_config (plci);
10447   }
10448   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10449     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10450     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10451 }
10452
10453
10454 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10455 {
10456   DIVA_CAPI_ADAPTER   *a;
10457   PLCI   *splci;
10458   byte ch, old_id;
10459
10460   a = plci->adapter;
10461   old_id = plci->li_bchannel_id;
10462   ch = chi_to_channel (chi, NULL);
10463   if (!(ch & 0x80))
10464   {
10465     if (a->li_pri)
10466     {
10467       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10468         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10469       plci->li_bchannel_id = (ch & 0x1f) + 1;
10470       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10471         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10472     }
10473     else
10474     {
10475       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10476       {
10477         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10478           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10479         plci->li_bchannel_id = ch & 0x1f;
10480         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10481         {
10482           splci = a->AdvSignalPLCI;
10483           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10484           {
10485             if ((splci->li_bchannel_id != 0)
10486              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10487             {
10488               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10489             }
10490             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10491             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10492             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10493               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10494               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10495           }
10496         }
10497         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10498           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10499       }
10500     }
10501   }
10502   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10503    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10504   {
10505     mixer_clear_config (plci);
10506   }
10507   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10508     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10509     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10510 }
10511
10512
10513 #define MIXER_MAX_DUMP_CHANNELS 34
10514
10515 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10516 {
10517 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10518   word n, i, j;
10519   char *p;
10520     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10521
10522   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10523     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10524
10525   for (i = 0; i < li_total_channels; i++)
10526   {
10527     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10528     if (li_config_table[i].chflags != 0)
10529       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10530     else
10531     {
10532       for (j = 0; j < li_total_channels; j++)
10533       {
10534         if (((li_config_table[i].flag_table[j]) != 0)
10535          || ((li_config_table[j].flag_table[i]) != 0))
10536         {
10537           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10538         }
10539         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10540          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10541         {
10542           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10543         }
10544       }
10545     }
10546   }
10547   for (i = 0; i < li_total_channels; i++)
10548   {
10549     for (j = 0; j < li_total_channels; j++)
10550     {
10551       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10552       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10553         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10554     }
10555   }
10556   for (n = 0; n < li_total_channels; n++)
10557   {
10558     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10559     {
10560       for (i = 0; i < li_total_channels; i++)
10561       {
10562         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10563         {
10564           for (j = 0; j < li_total_channels; j++)
10565           {
10566             li_config_table[i].coef_table[j] |=
10567               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10568           }
10569         }
10570       }
10571     }
10572   }
10573   for (i = 0; i < li_total_channels; i++)
10574   {
10575     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10576     {
10577       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10578       for (j = 0; j < li_total_channels; j++)
10579       {
10580         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10581           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10582       }
10583       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10584         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10585     }
10586   }
10587   for (i = 0; i < li_total_channels; i++)
10588   {
10589     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10590     {
10591       for (j = 0; j < li_total_channels; j++)
10592       {
10593         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10594           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10595         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10596           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10597         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10598           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10599         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10600           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10601       }
10602       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10603       {
10604         for (j = 0; j < li_total_channels; j++)
10605         {
10606           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10607           {
10608             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10609             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10610               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10611           }
10612         }
10613       }
10614       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10615       {
10616         for (j = 0; j < li_total_channels; j++)
10617         {
10618           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10619             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10620         }
10621       }
10622       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10623       {
10624         for (j = 0; j < li_total_channels; j++)
10625         {
10626           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10627           {
10628             for (n = 0; n < li_total_channels; n++)
10629             {
10630               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10631               {
10632                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10633                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10634                 {
10635                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10636                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10637                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10638                 }
10639                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10640                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10641               }
10642             }
10643           }
10644         }
10645       }
10646     }
10647   }
10648   for (i = 0; i < li_total_channels; i++)
10649   {
10650     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10651     {
10652       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10653         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10654       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10655         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10656       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10657         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10658       for (j = 0; j < li_total_channels; j++)
10659       {
10660         if ((li_config_table[i].flag_table[j] &
10661           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10662          || (li_config_table[j].flag_table[i] &
10663           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10664         {
10665           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10666         }
10667         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10668           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10669         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10670           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10671       }
10672       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10673       {
10674         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10675         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10676       }
10677     }
10678   }
10679   for (i = 0; i < li_total_channels; i++)
10680   {
10681     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10682     {
10683       j = 0;
10684       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10685         j++;
10686       if (j < li_total_channels)
10687       {
10688         for (j = 0; j < li_total_channels; j++)
10689         {
10690           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10691           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10692             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10693         }
10694       }
10695     }
10696   }
10697   n = li_total_channels;
10698   if (n > MIXER_MAX_DUMP_CHANNELS)
10699     n = MIXER_MAX_DUMP_CHANNELS;
10700   p = hex_line;
10701   for (j = 0; j < n; j++)
10702   {
10703     if ((j & 0x7) == 0)
10704       *(p++) = ' ';
10705     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10706     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10707   }
10708   *p = '\0';
10709   dbug (1, dprintf ("[%06lx] CURRENT %s",
10710     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10711   p = hex_line;
10712   for (j = 0; j < n; j++)
10713   {
10714     if ((j & 0x7) == 0)
10715       *(p++) = ' ';
10716     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10717     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10718   }
10719   *p = '\0';
10720   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10721     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10722   p = hex_line;
10723   for (j = 0; j < n; j++)
10724   {
10725     if ((j & 0x7) == 0)
10726       *(p++) = ' ';
10727     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10728     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10729   }
10730   *p = '\0';
10731   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10732     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10733   for (i = 0; i < n; i++)
10734   {
10735     p = hex_line;
10736     for (j = 0; j < n; j++)
10737     {
10738       if ((j & 0x7) == 0)
10739         *(p++) = ' ';
10740       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10741       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10742     }
10743     *p = '\0';
10744     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10745       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10746   }
10747   for (i = 0; i < n; i++)
10748   {
10749     p = hex_line;
10750     for (j = 0; j < n; j++)
10751     {
10752       if ((j & 0x7) == 0)
10753         *(p++) = ' ';
10754       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10755       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10756     }
10757     *p = '\0';
10758     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10759       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10760   }
10761 }
10762
10763
10764 static struct
10765 {
10766   byte mask;
10767   byte line_flags;
10768 } mixer_write_prog_pri[] =
10769 {
10770   { LI_COEF_CH_CH, 0 },
10771   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10772   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10773   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10774 };
10775
10776 static struct
10777 {
10778   byte from_ch;
10779   byte to_ch;
10780   byte mask;
10781   byte xconnect_override;
10782 } mixer_write_prog_bri[] =
10783 {
10784   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10785   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10786   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10787   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10788   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10789   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10790   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10791   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10792   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10793   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10794   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10795   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10796   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10797   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10798   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10799   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10800   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10801   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10802   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10803   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10804   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10805   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10806   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10807   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10808   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10809   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10810   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10811   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10812   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10813   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10814   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10815   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10816   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10817   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10818   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10819   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10820 };
10821
10822 static byte mixer_swapped_index_bri[] =
10823 {
10824   18,  /* B      to B      */
10825   19,  /* Alt B  to B      */
10826   20,  /* PC     to B      */
10827   21,  /* Alt PC to B      */
10828   22,  /* IC     to B      */
10829   23,  /* Alt IC to B      */
10830   24,  /* B      to PC     */
10831   25,  /* Alt B  to PC     */
10832   26,  /* PC     to PC     */
10833   27,  /* Alt PC to PC     */
10834   28,  /* IC     to PC     */
10835   29,  /* Alt IC to PC     */
10836   30,  /* B      to IC     */
10837   31,  /* Alt B  to IC     */
10838   32,  /* PC     to IC     */
10839   33,  /* Alt PC to IC     */
10840   34,  /* IC     to IC     */
10841   35,  /* Alt IC to IC     */
10842   0,   /* Alt B  to Alt B  */
10843   1,   /* B      to Alt B  */
10844   2,   /* Alt PC to Alt B  */
10845   3,   /* PC     to Alt B  */
10846   4,   /* Alt IC to Alt B  */
10847   5,   /* IC     to Alt B  */
10848   6,   /* Alt B  to Alt PC */
10849   7,   /* B      to Alt PC */
10850   8,   /* Alt PC to Alt PC */
10851   9,   /* PC     to Alt PC */
10852   10,  /* Alt IC to Alt PC */
10853   11,  /* IC     to Alt PC */
10854   12,  /* Alt B  to Alt IC */
10855   13,  /* B      to Alt IC */
10856   14,  /* Alt PC to Alt IC */
10857   15,  /* PC     to Alt IC */
10858   16,  /* Alt IC to Alt IC */
10859   17   /* IC     to Alt IC */
10860 };
10861
10862 static struct
10863 {
10864   byte mask;
10865   byte from_pc;
10866   byte to_pc;
10867 } xconnect_write_prog[] =
10868 {
10869   { LI_COEF_CH_CH, false, false },
10870   { LI_COEF_CH_PC, false, true },
10871   { LI_COEF_PC_CH, true, false },
10872   { LI_COEF_PC_PC, true, true }
10873 };
10874
10875
10876 static void xconnect_query_addresses (PLCI   *plci)
10877 {
10878   DIVA_CAPI_ADAPTER   *a;
10879   word w, ch;
10880   byte   *p;
10881
10882   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10883     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10884     (char   *)(FILE_), __LINE__));
10885
10886   a = plci->adapter;
10887   if (a->li_pri && ((plci->li_bchannel_id == 0)
10888    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10889   {
10890     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10891       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10892       (char   *)(FILE_), __LINE__));
10893     return;
10894   }
10895   p = plci->internal_req_buffer;
10896   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10897   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10898   w = ch;
10899   *(p++) = (byte) w;
10900   *(p++) = (byte)(w >> 8);
10901   w = ch | XCONNECT_CHANNEL_PORT_PC;
10902   *(p++) = (byte) w;
10903   *(p++) = (byte)(w >> 8);
10904   plci->NData[0].P = plci->internal_req_buffer;
10905   plci->NData[0].PLength = p - plci->internal_req_buffer;
10906   plci->NL.X = plci->NData;
10907   plci->NL.ReqCh = 0;
10908   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10909   plci->adapter->request (&plci->NL);
10910 }
10911
10912
10913 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10914 {
10915
10916   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10917     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10918     (char   *)(FILE_), __LINE__, internal_command));
10919
10920   plci->li_write_command = internal_command;
10921   plci->li_write_channel = 0;
10922 }
10923
10924
10925 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10926 {
10927   DIVA_CAPI_ADAPTER   *a;
10928   word w, n, i, j, r, s, to_ch;
10929   dword d;
10930   byte   *p;
10931   struct xconnect_transfer_address_s   *transfer_address;
10932   byte ch_map[MIXER_CHANNELS_BRI];
10933
10934   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10935     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10936
10937   a = plci->adapter;
10938   if ((plci->li_bchannel_id == 0)
10939    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10940   {
10941     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10942       UnMapId (Id), (char   *)(FILE_), __LINE__));
10943     return (true);
10944   }
10945   i = a->li_base + (plci->li_bchannel_id - 1);
10946   j = plci->li_write_channel;
10947   p = plci->internal_req_buffer;
10948   if (j != 0)
10949   {
10950     if ((Rc != OK) && (Rc != OK_FC))
10951     {
10952       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10953         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10954       return (false);
10955     }
10956   }
10957   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10958   {
10959     r = 0;
10960     s = 0;
10961     if (j < li_total_channels)
10962     {
10963       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10964       {
10965         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10966             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10967           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10968             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10969       }
10970       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10971       while ((j < li_total_channels)
10972         && ((r == 0)
10973          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10974          || (!li_config_table[j].adapter->li_pri
10975           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10976          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10977            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10978           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10979            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10980          || ((li_config_table[j].adapter->li_base != a->li_base)
10981           && !(r & s &
10982             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10983               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10984             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10985               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10986       {
10987         j++;
10988         if (j < li_total_channels)
10989           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10990       }
10991     }
10992     if (j < li_total_channels)
10993     {
10994       plci->internal_command = plci->li_write_command;
10995       if (plci_nl_busy (plci))
10996         return (true);
10997       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10998       *(p++) = UDATA_REQUEST_XCONNECT_TO;
10999       do
11000       {
11001         if (li_config_table[j].adapter->li_base != a->li_base)
11002         {
11003           r &= s &
11004             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11005               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11006             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11007               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11008         }
11009         n = 0;
11010         do
11011         {
11012           if (r & xconnect_write_prog[n].mask)
11013           {
11014             if (xconnect_write_prog[n].from_pc)
11015               transfer_address = &(li_config_table[j].send_pc);
11016             else
11017               transfer_address = &(li_config_table[j].send_b);
11018             d = transfer_address->card_address.low;
11019             *(p++) = (byte) d;
11020             *(p++) = (byte)(d >> 8);
11021             *(p++) = (byte)(d >> 16);
11022             *(p++) = (byte)(d >> 24);
11023             d = transfer_address->card_address.high;
11024             *(p++) = (byte) d;
11025             *(p++) = (byte)(d >> 8);
11026             *(p++) = (byte)(d >> 16);
11027             *(p++) = (byte)(d >> 24);
11028             d = transfer_address->offset;
11029             *(p++) = (byte) d;
11030             *(p++) = (byte)(d >> 8);
11031             *(p++) = (byte)(d >> 16);
11032             *(p++) = (byte)(d >> 24);
11033             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11034             *(p++) = (byte) w;
11035             *(p++) = (byte)(w >> 8);
11036             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11037               (li_config_table[i].adapter->u_law ?
11038                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11039                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11040             *(p++) = (byte) w;
11041             *(p++) = (byte) 0;
11042             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11043           }
11044           n++;
11045         } while ((n < ARRAY_SIZE(xconnect_write_prog))
11046           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11047         if (n == ARRAY_SIZE(xconnect_write_prog))
11048         {
11049           do
11050           {
11051             j++;
11052             if (j < li_total_channels)
11053               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11054           } while ((j < li_total_channels)
11055             && ((r == 0)
11056              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11057              || (!li_config_table[j].adapter->li_pri
11058               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11059              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11060                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11061               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11062                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11063              || ((li_config_table[j].adapter->li_base != a->li_base)
11064               && !(r & s &
11065                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11066                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11067                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11068                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11069         }
11070       } while ((j < li_total_channels)
11071         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11072     }
11073     else if (j == li_total_channels)
11074     {
11075       plci->internal_command = plci->li_write_command;
11076       if (plci_nl_busy (plci))
11077         return (true);
11078       if (a->li_pri)
11079       {
11080         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11081         w = 0;
11082         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11083           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11084         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11085           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11086         *(p++) = (byte) w;
11087         *(p++) = (byte)(w >> 8);
11088       }
11089       else
11090       {
11091         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11092         w = 0;
11093         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11094          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11095         {
11096           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11097         }
11098         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11099           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11100         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11101           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11102         *(p++) = (byte) w;
11103         *(p++) = (byte)(w >> 8);
11104         for (j = 0; j < sizeof(ch_map); j += 2)
11105         {
11106           if (plci->li_bchannel_id == 2)
11107           {
11108             ch_map[j] = (byte)(j+1);
11109             ch_map[j+1] = (byte) j;
11110           }
11111           else
11112           {
11113             ch_map[j] = (byte) j;
11114             ch_map[j+1] = (byte)(j+1);
11115           }
11116         }
11117         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11118         {
11119           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11120           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11121           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11122           {
11123             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11124               mixer_write_prog_bri[n].xconnect_override :
11125               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11126             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11127             {
11128               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11129               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11130             }
11131           }
11132           else
11133           {
11134             *p = 0x00;
11135             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11136             {
11137               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11138               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11139                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11140             }
11141           }
11142           p++;
11143         }
11144       }
11145       j = li_total_channels + 1;
11146     }
11147   }
11148   else
11149   {
11150     if (j <= li_total_channels)
11151     {
11152       plci->internal_command = plci->li_write_command;
11153       if (plci_nl_busy (plci))
11154         return (true);
11155       if (j < a->li_base)
11156         j = a->li_base;
11157       if (a->li_pri)
11158       {
11159         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11160         w = 0;
11161         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11162           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11163         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11164           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11165         *(p++) = (byte) w;
11166         *(p++) = (byte)(w >> 8);
11167         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11168         {
11169           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11170           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11171           {
11172             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11173             if (w & mixer_write_prog_pri[n].mask)
11174             {
11175               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11176               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11177             }
11178             else
11179               *(p++) = 0x00;
11180           }
11181           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11182           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11183           {
11184             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11185             if (w & mixer_write_prog_pri[n].mask)
11186             {
11187               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11188               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11189             }
11190             else
11191               *(p++) = 0x00;
11192           }
11193         }
11194       }
11195       else
11196       {
11197         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11198         w = 0;
11199         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11200          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11201         {
11202           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11203         }
11204         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11205           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11206         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11207           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11208         *(p++) = (byte) w;
11209         *(p++) = (byte)(w >> 8);
11210         for (j = 0; j < sizeof(ch_map); j += 2)
11211         {
11212           if (plci->li_bchannel_id == 2)
11213           {
11214             ch_map[j] = (byte)(j+1);
11215             ch_map[j+1] = (byte) j;
11216           }
11217           else
11218           {
11219             ch_map[j] = (byte) j;
11220             ch_map[j+1] = (byte)(j+1);
11221           }
11222         }
11223         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11224         {
11225           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11226           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11227           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11228           {
11229             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11230             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11231             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11232           }
11233           else
11234           {
11235             *p = 0x00;
11236             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11237             {
11238               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11239               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11240                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11241             }
11242           }
11243           p++;
11244         }
11245       }
11246       j = li_total_channels + 1;
11247     }
11248   }
11249   plci->li_write_channel = j;
11250   if (p != plci->internal_req_buffer)
11251   {
11252     plci->NData[0].P = plci->internal_req_buffer;
11253     plci->NData[0].PLength = p - plci->internal_req_buffer;
11254     plci->NL.X = plci->NData;
11255     plci->NL.ReqCh = 0;
11256     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11257     plci->adapter->request (&plci->NL);
11258   }
11259   return (true);
11260 }
11261
11262
11263 static void mixer_notify_update (PLCI   *plci, byte others)
11264 {
11265   DIVA_CAPI_ADAPTER   *a;
11266   word i, w;
11267   PLCI   *notify_plci;
11268     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11269
11270   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11271     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11272     (char   *)(FILE_), __LINE__, others));
11273
11274   a = plci->adapter;
11275   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11276   {
11277     if (others)
11278       plci->li_notify_update = true;
11279     i = 0;
11280     do
11281     {
11282       notify_plci = NULL;
11283       if (others)
11284       {
11285         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11286           i++;
11287         if (i < li_total_channels)
11288           notify_plci = li_config_table[i++].plci;
11289       }
11290       else
11291       {
11292         if ((plci->li_bchannel_id != 0)
11293          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11294         {
11295           notify_plci = plci;
11296         }
11297       }
11298       if ((notify_plci != NULL)
11299        && !notify_plci->li_notify_update
11300        && (notify_plci->appl != NULL)
11301        && (notify_plci->State)
11302        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11303       {
11304         notify_plci->li_notify_update = true;
11305         ((CAPI_MSG *) msg)->header.length = 18;
11306         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11307         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11308         ((CAPI_MSG *) msg)->header.number = 0;
11309         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11310         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11311         ((CAPI_MSG *) msg)->header.ncci = 0;
11312         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11313         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11314         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11315         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11316         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11317         if (w != _QUEUE_FULL)
11318         {
11319           if (w != 0)
11320           {
11321             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11322               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11323               (char   *)(FILE_), __LINE__,
11324               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11325           }
11326           notify_plci->li_notify_update = false;
11327         }
11328       }
11329     } while (others && (notify_plci != NULL));
11330     if (others)
11331       plci->li_notify_update = false;
11332   }
11333 }
11334
11335
11336 static void mixer_clear_config (PLCI   *plci)
11337 {
11338   DIVA_CAPI_ADAPTER   *a;
11339   word i, j;
11340
11341   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11342     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11343     (char   *)(FILE_), __LINE__));
11344
11345   plci->li_notify_update = false;
11346   plci->li_plci_b_write_pos = 0;
11347   plci->li_plci_b_read_pos = 0;
11348   plci->li_plci_b_req_pos = 0;
11349   a = plci->adapter;
11350   if ((plci->li_bchannel_id != 0)
11351    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11352   {
11353     i = a->li_base + (plci->li_bchannel_id - 1);
11354     li_config_table[i].curchnl = 0;
11355     li_config_table[i].channel = 0;
11356     li_config_table[i].chflags = 0;
11357     for (j = 0; j < li_total_channels; j++)
11358     {
11359       li_config_table[j].flag_table[i] = 0;
11360       li_config_table[i].flag_table[j] = 0;
11361       li_config_table[i].coef_table[j] = 0;
11362       li_config_table[j].coef_table[i] = 0;
11363     }
11364     if (!a->li_pri)
11365     {
11366       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11367       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11368       {
11369         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11370         li_config_table[i].curchnl = 0;
11371         li_config_table[i].channel = 0;
11372         li_config_table[i].chflags = 0;
11373         for (j = 0; j < li_total_channels; j++)
11374         {
11375           li_config_table[i].flag_table[j] = 0;
11376           li_config_table[j].flag_table[i] = 0;
11377           li_config_table[i].coef_table[j] = 0;
11378           li_config_table[j].coef_table[i] = 0;
11379         }
11380         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11381         {
11382           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11383           li_config_table[i].curchnl = 0;
11384           li_config_table[i].channel = 0;
11385           li_config_table[i].chflags = 0;
11386           for (j = 0; j < li_total_channels; j++)
11387           {
11388             li_config_table[i].flag_table[j] = 0;
11389             li_config_table[j].flag_table[i] = 0;
11390             li_config_table[i].coef_table[j] = 0;
11391             li_config_table[j].coef_table[i] = 0;
11392           }
11393         }
11394       }
11395     }
11396   }
11397 }
11398
11399
11400 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11401 {
11402
11403   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11404     UnMapId (Id), (char   *)(FILE_), __LINE__));
11405
11406   do
11407   {
11408     mixer_indication_coefs_set (Id, plci);
11409   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11410 }
11411
11412
11413 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11414 {
11415   DIVA_CAPI_ADAPTER   *a;
11416   word i, j;
11417
11418   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11419     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11420
11421   a = plci->adapter;
11422   if ((plci->li_bchannel_id != 0)
11423    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11424   {
11425     i = a->li_base + (plci->li_bchannel_id - 1);
11426     for (j = 0; j < li_total_channels; j++)
11427     {
11428       li_config_table[i].coef_table[j] &= 0xf;
11429       li_config_table[j].coef_table[i] &= 0xf;
11430     }
11431     if (!a->li_pri)
11432       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11433   }
11434   return (GOOD);
11435 }
11436
11437
11438 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11439 {
11440   DIVA_CAPI_ADAPTER   *a;
11441   word Info;
11442
11443   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11444     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11445
11446   Info = GOOD;
11447   a = plci->adapter;
11448   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11449    && (plci->li_bchannel_id != 0)
11450    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11451   {
11452     switch (plci->adjust_b_state)
11453     {
11454     case ADJUST_B_RESTORE_MIXER_1:
11455       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11456       {
11457         plci->internal_command = plci->adjust_b_command;
11458         if (plci_nl_busy (plci))
11459         {
11460           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11461           break;
11462         }
11463         xconnect_query_addresses (plci);
11464         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11465         break;
11466       }
11467       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11468       Rc = OK;
11469     case ADJUST_B_RESTORE_MIXER_2:
11470     case ADJUST_B_RESTORE_MIXER_3:
11471     case ADJUST_B_RESTORE_MIXER_4:
11472       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11473       {
11474         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11475           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11476         Info = _WRONG_STATE;
11477         break;
11478       }
11479       if (Rc == OK)
11480       {
11481         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11482           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11483         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11484           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11485       }
11486       else if (Rc == 0)
11487       {
11488         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11489           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11490         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11491           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11492       }
11493       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11494       {
11495         plci->internal_command = plci->adjust_b_command;
11496         break;
11497       }
11498     case ADJUST_B_RESTORE_MIXER_5:
11499       xconnect_write_coefs (plci, plci->adjust_b_command);
11500       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11501       Rc = OK;
11502     case ADJUST_B_RESTORE_MIXER_6:
11503       if (!xconnect_write_coefs_process (Id, plci, Rc))
11504       {
11505         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11506           UnMapId (Id), (char   *)(FILE_), __LINE__));
11507         Info = _FACILITY_NOT_SUPPORTED;
11508         break;
11509       }
11510       if (plci->internal_command)
11511         break;
11512       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11513     case ADJUST_B_RESTORE_MIXER_7:
11514       break;
11515     }
11516   }
11517   return (Info);
11518 }
11519
11520
11521 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11522 {
11523   DIVA_CAPI_ADAPTER   *a;
11524   word i, internal_command, Info;
11525
11526   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11527     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11528     plci->li_cmd));
11529
11530   Info = GOOD;
11531   a = plci->adapter;
11532   internal_command = plci->internal_command;
11533   plci->internal_command = 0;
11534   switch (plci->li_cmd)
11535   {
11536   case LI_REQ_CONNECT:
11537   case LI_REQ_DISCONNECT:
11538   case LI_REQ_SILENT_UPDATE:
11539     switch (internal_command)
11540     {
11541     default:
11542       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11543       {
11544         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11545           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11546       }
11547     case MIXER_COMMAND_1:
11548       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11549       {
11550         if (adjust_b_process (Id, plci, Rc) != GOOD)
11551         {
11552           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11553             UnMapId (Id), (char   *)(FILE_), __LINE__));
11554           Info = _FACILITY_NOT_SUPPORTED;
11555           break;
11556         }
11557         if (plci->internal_command)
11558           return;
11559       }
11560       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11561       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11562        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11563         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11564          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11565       {
11566         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11567       }
11568       else
11569       {
11570         do
11571         {
11572           mixer_indication_coefs_set (Id, plci);
11573         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11574       }
11575     case MIXER_COMMAND_2:
11576       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11577        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11578         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11579          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11580       {
11581         if (!xconnect_write_coefs_process (Id, plci, Rc))
11582         {
11583           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11584             UnMapId (Id), (char   *)(FILE_), __LINE__));
11585           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11586           {
11587             do
11588             {
11589               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11590                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11591               i = (plci->li_plci_b_write_pos == 0) ?
11592                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11593             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11594               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11595           }
11596           Info = _FACILITY_NOT_SUPPORTED;
11597           break;
11598         }
11599         if (plci->internal_command)
11600           return;
11601       }
11602       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11603       {
11604         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11605           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11606       }
11607     case MIXER_COMMAND_3:
11608       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11609       {
11610         if (adjust_b_process (Id, plci, Rc) != GOOD)
11611         {
11612           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11613             UnMapId (Id), (char   *)(FILE_), __LINE__));
11614           Info = _FACILITY_NOT_SUPPORTED;
11615           break;
11616         }
11617         if (plci->internal_command)
11618           return;
11619       }
11620       break;
11621     }
11622     break;
11623   }
11624   if ((plci->li_bchannel_id == 0)
11625    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11626   {
11627     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11628       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11629   }
11630   else
11631   {
11632     i = a->li_base + (plci->li_bchannel_id - 1);
11633     li_config_table[i].curchnl = plci->li_channel_bits;
11634     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11635     {
11636       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11637       li_config_table[i].curchnl = plci->li_channel_bits;
11638       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11639       {
11640         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11641         li_config_table[i].curchnl = plci->li_channel_bits;
11642       }
11643     }
11644   }
11645 }
11646
11647
11648 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11649   dword plci_b_id, byte connect, dword li_flags)
11650 {
11651   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11652   PLCI   *plci_b;
11653   DIVA_CAPI_ADAPTER   *a_b;
11654
11655   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11656   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11657   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11658   if (!a->li_pri && (plci->tel == ADV_VOICE)
11659    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11660   {
11661     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11662     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11663       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11664   }
11665   else
11666   {
11667     ch_a_v = ch_a;
11668     ch_a_s = ch_a;
11669   }
11670   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11671   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11672    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11673   {
11674     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11675     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11676       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11677   }
11678   else
11679   {
11680     ch_b_v = ch_b;
11681     ch_b_s = ch_b;
11682   }
11683   if (connect)
11684   {
11685     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11686     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11687     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11688     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11689   }
11690   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11691   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11692   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11693   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11694   if (ch_a_v == ch_b_v)
11695   {
11696     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11697     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11698   }
11699   else
11700   {
11701     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11702     {
11703       for (i = 0; i < li_total_channels; i++)
11704       {
11705         if (i != ch_a_v)
11706           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11707       }
11708     }
11709     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11710     {
11711       for (i = 0; i < li_total_channels; i++)
11712       {
11713         if (i != ch_a_s)
11714           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11715       }
11716     }
11717     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11718     {
11719       for (i = 0; i < li_total_channels; i++)
11720       {
11721         if (i != ch_a_v)
11722           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11723       }
11724     }
11725     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11726     {
11727       for (i = 0; i < li_total_channels; i++)
11728       {
11729         if (i != ch_a_s)
11730           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11731       }
11732     }
11733   }
11734   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11735   {
11736     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11737     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11738     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11739     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11740   }
11741   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11742   {
11743     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11744     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11745     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11746     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11747   }
11748   if (li_flags & LI_FLAG_MONITOR_A)
11749   {
11750     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11751     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11752   }
11753   if (li_flags & LI_FLAG_MONITOR_B)
11754   {
11755     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11756     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11757   }
11758   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11759   {
11760     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11761     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11762   }
11763   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11764   {
11765     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11766     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11767   }
11768   if (li_flags & LI_FLAG_MIX_A)
11769   {
11770     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11771     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11772   }
11773   if (li_flags & LI_FLAG_MIX_B)
11774   {
11775     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11776     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11777   }
11778   if (ch_a_v != ch_a_s)
11779   {
11780     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11781     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11782   }
11783   if (ch_b_v != ch_b_s)
11784   {
11785     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11786     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11787   }
11788 }
11789
11790
11791 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11792   dword plci_b_id, byte connect, dword li_flags)
11793 {
11794   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11795   PLCI   *plci_b;
11796   DIVA_CAPI_ADAPTER   *a_b;
11797
11798   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11799   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11800   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11801   if (!a->li_pri && (plci->tel == ADV_VOICE)
11802    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11803   {
11804     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11805     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11806       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11807   }
11808   else
11809   {
11810     ch_a_v = ch_a;
11811     ch_a_s = ch_a;
11812   }
11813   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11814   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11815    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11816   {
11817     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11818     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11819       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11820   }
11821   else
11822   {
11823     ch_b_v = ch_b;
11824     ch_b_s = ch_b;
11825   }
11826   if (connect)
11827   {
11828     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11829     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11830     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11831     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11832     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11833     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11834   }
11835   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11836   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11837   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11838   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11839   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11840   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11841   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11842   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11843   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11844   {
11845     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11846     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11847     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11848     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11849   }
11850   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11851   {
11852     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11853     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11854     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856   }
11857   if (li_flags & LI2_FLAG_MONITOR_B)
11858   {
11859     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11860     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11861   }
11862   if (li_flags & LI2_FLAG_MIX_B)
11863   {
11864     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11865     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11866   }
11867   if (li_flags & LI2_FLAG_MONITOR_X)
11868     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11869   if (li_flags & LI2_FLAG_MIX_X)
11870     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11871   if (li_flags & LI2_FLAG_LOOP_B)
11872   {
11873     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11874     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11875     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11876     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11877   }
11878   if (li_flags & LI2_FLAG_LOOP_PC)
11879     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11880   if (li_flags & LI2_FLAG_LOOP_X)
11881     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11882   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11883     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11884   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11885     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11886   if (ch_a_v != ch_a_s)
11887   {
11888     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11889     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11890   }
11891   if (ch_b_v != ch_b_s)
11892   {
11893     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11894     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11895   }
11896 }
11897
11898
11899 static word li_check_main_plci (dword Id, PLCI   *plci)
11900 {
11901   if (plci == NULL)
11902   {
11903     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11904       UnMapId (Id), (char   *)(FILE_), __LINE__));
11905     return (_WRONG_IDENTIFIER);
11906   }
11907   if (!plci->State
11908    || !plci->NL.Id || plci->nl_remove_id
11909    || (plci->li_bchannel_id == 0))
11910   {
11911     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11912       UnMapId (Id), (char   *)(FILE_), __LINE__));
11913     return (_WRONG_STATE);
11914   }
11915   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11916   return (GOOD);
11917 }
11918
11919
11920 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11921   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11922 {
11923   byte ctlr_b;
11924   PLCI   *plci_b;
11925
11926   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11927     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11928   {
11929     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11930       UnMapId (Id), (char   *)(FILE_), __LINE__));
11931     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11932     return (NULL);
11933   }
11934   ctlr_b = 0;
11935   if ((plci_b_id & 0x7f) != 0)
11936   {
11937     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11938     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11939       ctlr_b = 0;
11940   }
11941   if ((ctlr_b == 0)
11942    || (((plci_b_id >> 8) & 0xff) == 0)
11943    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11944   {
11945     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11946       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11947     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11948     return (NULL);
11949   }
11950   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11951   if (!plci_b->State
11952    || !plci_b->NL.Id || plci_b->nl_remove_id
11953    || (plci_b->li_bchannel_id == 0))
11954   {
11955     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11956       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11957     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11958     return (NULL);
11959   }
11960   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11961   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11962     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11963    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11964     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11965   {
11966     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11967       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11968     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11969     return (NULL);
11970   }
11971   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11972     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11973   {
11974     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11975       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11976     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11977     return (NULL);
11978   }
11979   return (plci_b);
11980 }
11981
11982
11983 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11984   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11985 {
11986   byte ctlr_b;
11987   PLCI   *plci_b;
11988
11989   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11990     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11991   {
11992     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11993       UnMapId (Id), (char   *)(FILE_), __LINE__));
11994     PUT_WORD (p_result, _WRONG_STATE);
11995     return (NULL);
11996   }
11997   ctlr_b = 0;
11998   if ((plci_b_id & 0x7f) != 0)
11999   {
12000     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
12001     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
12002       ctlr_b = 0;
12003   }
12004   if ((ctlr_b == 0)
12005    || (((plci_b_id >> 8) & 0xff) == 0)
12006    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
12007   {
12008     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
12009       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12010     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12011     return (NULL);
12012   }
12013   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12014   if (!plci_b->State
12015    || !plci_b->NL.Id || plci_b->nl_remove_id
12016    || (plci_b->li_bchannel_id == 0)
12017    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12018   {
12019     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12020       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12021     PUT_WORD (p_result, _WRONG_STATE);
12022     return (NULL);
12023   }
12024   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12025     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12026    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12027     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12028   {
12029     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12030       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12031     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12032     return (NULL);
12033   }
12034   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12035     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12036   {
12037     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12038       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12039     PUT_WORD (p_result, _WRONG_STATE);
12040     return (NULL);
12041   }
12042   return (plci_b);
12043 }
12044
12045
12046 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12047 {
12048   word Info;
12049   word i;
12050   dword d, li_flags, plci_b_id;
12051   PLCI   *plci_b;
12052     API_PARSE li_parms[3];
12053     API_PARSE li_req_parms[3];
12054     API_PARSE li_participant_struct[2];
12055     API_PARSE li_participant_parms[3];
12056   word participant_parms_pos;
12057   byte result_buffer[32];
12058   byte   *result;
12059   word result_pos;
12060   word plci_b_write_pos;
12061
12062   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12063     UnMapId (Id), (char   *)(FILE_), __LINE__));
12064
12065   Info = GOOD;
12066   result = result_buffer;
12067   result_buffer[0] = 0;
12068   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12069   {
12070     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12071       UnMapId (Id), (char   *)(FILE_), __LINE__));
12072     Info = _FACILITY_NOT_SUPPORTED;
12073   }
12074   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12075   {
12076     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12077       UnMapId (Id), (char   *)(FILE_), __LINE__));
12078     Info = _WRONG_MESSAGE_FORMAT;
12079   }
12080   else
12081   {
12082     result_buffer[0] = 3;
12083     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12084     result_buffer[3] = 0;
12085     switch (GET_WORD (li_parms[0].info))
12086     {
12087     case LI_GET_SUPPORTED_SERVICES:
12088       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12089       {
12090         result_buffer[0] = 17;
12091         result_buffer[3] = 14;
12092         PUT_WORD (&result_buffer[4], GOOD);
12093         d = 0;
12094         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12095           d |= LI_CONFERENCING_SUPPORTED;
12096         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12097           d |= LI_MONITORING_SUPPORTED;
12098         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12099           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12100         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12101           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12102         PUT_DWORD (&result_buffer[6], d);
12103         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12104         {
12105           d = 0;
12106           for (i = 0; i < li_total_channels; i++)
12107           {
12108             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12109              && (li_config_table[i].adapter->li_pri
12110               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12111             {
12112               d++;
12113             }
12114           }
12115         }
12116         else
12117         {
12118           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12119         }
12120         PUT_DWORD (&result_buffer[10], d / 2);
12121         PUT_DWORD (&result_buffer[14], d);
12122       }
12123       else
12124       {
12125         result_buffer[0] = 25;
12126         result_buffer[3] = 22;
12127         PUT_WORD (&result_buffer[4], GOOD);
12128         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12129         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12130           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12131         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12132           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12133         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12134           d |= LI2_PC_LOOPING_SUPPORTED;
12135         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12136           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12137         PUT_DWORD (&result_buffer[6], d);
12138         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12139         PUT_DWORD (&result_buffer[10], d / 2);
12140         PUT_DWORD (&result_buffer[14], d - 1);
12141         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12142         {
12143           d = 0;
12144           for (i = 0; i < li_total_channels; i++)
12145           {
12146             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12147              && (li_config_table[i].adapter->li_pri
12148               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12149             {
12150               d++;
12151             }
12152           }
12153         }
12154         PUT_DWORD (&result_buffer[18], d / 2);
12155         PUT_DWORD (&result_buffer[22], d - 1);
12156       }
12157       break;
12158
12159     case LI_REQ_CONNECT:
12160       if (li_parms[1].length == 8)
12161       {
12162         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12163         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12164         {
12165           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12166             UnMapId (Id), (char   *)(FILE_), __LINE__));
12167           Info = _WRONG_MESSAGE_FORMAT;
12168           break;
12169         }
12170         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12171         li_flags = GET_DWORD (li_req_parms[1].info);
12172         Info = li_check_main_plci (Id, plci);
12173         result_buffer[0] = 9;
12174         result_buffer[3] = 6;
12175         PUT_DWORD (&result_buffer[4], plci_b_id);
12176         PUT_WORD (&result_buffer[8], GOOD);
12177         if (Info != GOOD)
12178           break;
12179         result = plci->saved_msg.info;
12180         for (i = 0; i <= result_buffer[0]; i++)
12181           result[i] = result_buffer[i];
12182         plci_b_write_pos = plci->li_plci_b_write_pos;
12183         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12184         if (plci_b == NULL)
12185           break;
12186         li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12187         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12188         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12189         plci->li_plci_b_write_pos = plci_b_write_pos;
12190       }
12191       else
12192       {
12193         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12194         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12195         {
12196           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12197             UnMapId (Id), (char   *)(FILE_), __LINE__));
12198           Info = _WRONG_MESSAGE_FORMAT;
12199           break;
12200         }
12201         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12202         Info = li_check_main_plci (Id, plci);
12203         result_buffer[0] = 7;
12204         result_buffer[3] = 4;
12205         PUT_WORD (&result_buffer[4], Info);
12206         result_buffer[6] = 0;
12207         if (Info != GOOD)
12208           break;
12209         result = plci->saved_msg.info;
12210         for (i = 0; i <= result_buffer[0]; i++)
12211           result[i] = result_buffer[i];
12212         plci_b_write_pos = plci->li_plci_b_write_pos;
12213         participant_parms_pos = 0;
12214         result_pos = 7;
12215         li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12216         while (participant_parms_pos < li_req_parms[1].length)
12217         {
12218           result[result_pos] = 6;
12219           result_pos += 7;
12220           PUT_DWORD (&result[result_pos - 6], 0);
12221           PUT_WORD (&result[result_pos - 2], GOOD);
12222           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12223             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12224           {
12225             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12226               UnMapId (Id), (char   *)(FILE_), __LINE__));
12227             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12228             break;
12229           }
12230           if (api_parse (&li_participant_struct[0].info[1],
12231             li_participant_struct[0].length, "dd", li_participant_parms))
12232           {
12233             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12234               UnMapId (Id), (char   *)(FILE_), __LINE__));
12235             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12236             break;
12237           }
12238           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12239           li_flags = GET_DWORD (li_participant_parms[1].info);
12240           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12241           if (sizeof(result) - result_pos < 7)
12242           {
12243             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12244               UnMapId (Id), (char   *)(FILE_), __LINE__));
12245             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12246             break;
12247           }
12248           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12249           if (plci_b != NULL)
12250           {
12251             li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12252             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12253               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12254               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12255             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12256           }
12257           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12258             (&li_req_parms[1].info[1]));
12259         }
12260         result[0] = (byte)(result_pos - 1);
12261         result[3] = (byte)(result_pos - 4);
12262         result[6] = (byte)(result_pos - 7);
12263         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12264         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12265          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12266         {
12267           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12268           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12269         }
12270         else
12271           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12272         plci->li_plci_b_write_pos = plci_b_write_pos;
12273       }
12274       mixer_calculate_coefs (a);
12275       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12276       mixer_notify_update (plci, true);
12277       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12278         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12279       plci->command = 0;
12280       plci->li_cmd = GET_WORD (li_parms[0].info);
12281       start_internal_command (Id, plci, mixer_command);
12282       return (false);
12283
12284     case LI_REQ_DISCONNECT:
12285       if (li_parms[1].length == 4)
12286       {
12287         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12288         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12289         {
12290           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12291             UnMapId (Id), (char   *)(FILE_), __LINE__));
12292           Info = _WRONG_MESSAGE_FORMAT;
12293           break;
12294         }
12295         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12296         Info = li_check_main_plci (Id, plci);
12297         result_buffer[0] = 9;
12298         result_buffer[3] = 6;
12299         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12300         PUT_WORD (&result_buffer[8], GOOD);
12301         if (Info != GOOD)
12302           break;
12303         result = plci->saved_msg.info;
12304         for (i = 0; i <= result_buffer[0]; i++)
12305           result[i] = result_buffer[i];
12306         plci_b_write_pos = plci->li_plci_b_write_pos;
12307         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12308         if (plci_b == NULL)
12309           break;
12310         li_update_connect (Id, a, plci, plci_b_id, false, 0);
12311         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12312         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12313         plci->li_plci_b_write_pos = plci_b_write_pos;
12314       }
12315       else
12316       {
12317         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12318         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12319         {
12320           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12321             UnMapId (Id), (char   *)(FILE_), __LINE__));
12322           Info = _WRONG_MESSAGE_FORMAT;
12323           break;
12324         }
12325         Info = li_check_main_plci (Id, plci);
12326         result_buffer[0] = 7;
12327         result_buffer[3] = 4;
12328         PUT_WORD (&result_buffer[4], Info);
12329         result_buffer[6] = 0;
12330         if (Info != GOOD)
12331           break;
12332         result = plci->saved_msg.info;
12333         for (i = 0; i <= result_buffer[0]; i++)
12334           result[i] = result_buffer[i];
12335         plci_b_write_pos = plci->li_plci_b_write_pos;
12336         participant_parms_pos = 0;
12337         result_pos = 7;
12338         while (participant_parms_pos < li_req_parms[0].length)
12339         {
12340           result[result_pos] = 6;
12341           result_pos += 7;
12342           PUT_DWORD (&result[result_pos - 6], 0);
12343           PUT_WORD (&result[result_pos - 2], GOOD);
12344           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12345             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12346           {
12347             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12348               UnMapId (Id), (char   *)(FILE_), __LINE__));
12349             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12350             break;
12351           }
12352           if (api_parse (&li_participant_struct[0].info[1],
12353             li_participant_struct[0].length, "d", li_participant_parms))
12354           {
12355             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12356               UnMapId (Id), (char   *)(FILE_), __LINE__));
12357             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12358             break;
12359           }
12360           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12361           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12362           if (sizeof(result) - result_pos < 7)
12363           {
12364             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12365               UnMapId (Id), (char   *)(FILE_), __LINE__));
12366             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12367             break;
12368           }
12369           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12370           if (plci_b != NULL)
12371           {
12372             li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12373             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12374             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12375           }
12376           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12377             (&li_req_parms[0].info[1]));
12378         }
12379         result[0] = (byte)(result_pos - 1);
12380         result[3] = (byte)(result_pos - 4);
12381         result[6] = (byte)(result_pos - 7);
12382         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12383         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12384          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12385         {
12386           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12387           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12388         }
12389         else
12390           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12391         plci->li_plci_b_write_pos = plci_b_write_pos;
12392       }
12393       mixer_calculate_coefs (a);
12394       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12395       mixer_notify_update (plci, true);
12396       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12397         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12398       plci->command = 0;
12399       plci->li_cmd = GET_WORD (li_parms[0].info);
12400       start_internal_command (Id, plci, mixer_command);
12401       return (false);
12402
12403     case LI_REQ_SILENT_UPDATE:
12404       if (!plci || !plci->State
12405        || !plci->NL.Id || plci->nl_remove_id
12406        || (plci->li_bchannel_id == 0)
12407        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12408       {
12409         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12410           UnMapId (Id), (char   *)(FILE_), __LINE__));
12411         return (false);
12412       }
12413       plci_b_write_pos = plci->li_plci_b_write_pos;
12414       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12415         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12416       {
12417         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12418           UnMapId (Id), (char   *)(FILE_), __LINE__));
12419         return (false);
12420       }
12421       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12422       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12423        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12424       {
12425         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12426         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12427       }
12428       else
12429         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12430       plci->li_plci_b_write_pos = plci_b_write_pos;
12431       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12432       plci->command = 0;
12433       plci->li_cmd = GET_WORD (li_parms[0].info);
12434       start_internal_command (Id, plci, mixer_command);
12435       return (false);
12436
12437     default:
12438       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12439         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12440       Info = _FACILITY_NOT_SUPPORTED;
12441     }
12442   }
12443   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12444     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12445   return (false);
12446 }
12447
12448
12449 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12450 {
12451   dword d;
12452   DIVA_CAPI_ADAPTER   *a;
12453     byte result[12];
12454
12455   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12456     UnMapId (Id), (char   *)(FILE_), __LINE__));
12457
12458   a = plci->adapter;
12459   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12460   {
12461     do
12462     {
12463       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12464       if (!(d & LI_PLCI_B_SKIP_FLAG))
12465       {
12466         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12467         {
12468           if (d & LI_PLCI_B_DISC_FLAG)
12469           {
12470             result[0] = 5;
12471             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12472             result[3] = 2;
12473             PUT_WORD (&result[4], _LI_USER_INITIATED);
12474           }
12475           else
12476           {
12477             result[0] = 7;
12478             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12479             result[3] = 4;
12480             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12481           }
12482         }
12483         else
12484         {
12485           if (d & LI_PLCI_B_DISC_FLAG)
12486           {
12487             result[0] = 9;
12488             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12489             result[3] = 6;
12490             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12491             PUT_WORD (&result[8], _LI_USER_INITIATED);
12492           }
12493           else
12494           {
12495             result[0] = 7;
12496             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12497             result[3] = 4;
12498             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12499           }
12500         }
12501         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12502           "ws", SELECTOR_LINE_INTERCONNECT, result);
12503       }
12504       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12505         0 : plci->li_plci_b_read_pos + 1;
12506     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12507   }
12508 }
12509
12510
12511 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12512 {
12513   word i, j, ch;
12514   struct xconnect_transfer_address_s s,   *p;
12515   DIVA_CAPI_ADAPTER   *a;
12516
12517   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12518     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12519
12520   a = plci->adapter;
12521   i = 1;
12522   for (i = 1; i < length; i += 16)
12523   {
12524     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12525     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12526     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12527     ch = msg[i+12] | (msg[i+13] << 8);
12528     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12529     if (!a->li_pri && (plci->li_bchannel_id == 2))
12530       j = 1 - j;
12531     j += a->li_base;
12532     if (ch & XCONNECT_CHANNEL_PORT_PC)
12533       p = &(li_config_table[j].send_pc);
12534     else
12535       p = &(li_config_table[j].send_b);
12536     p->card_address.low = s.card_address.low;
12537     p->card_address.high = s.card_address.high;
12538     p->offset = s.offset;
12539     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12540   }
12541   if (plci->internal_command_queue[0]
12542    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12543     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12544     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12545   {
12546     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12547     if (!plci->internal_command)
12548       next_internal_command (Id, plci);
12549   }
12550   mixer_notify_update (plci, true);
12551 }
12552
12553
12554 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12555 {
12556
12557   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12558     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12559
12560 }
12561
12562
12563 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12564 {
12565   word plci_b_write_pos;
12566
12567   plci_b_write_pos = plci->li_plci_b_write_pos;
12568   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12569     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12570   {
12571     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12572       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12573       (char   *)(FILE_), __LINE__));
12574     return (false);
12575   }
12576   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12577   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12578   plci->li_plci_b_write_pos = plci_b_write_pos;
12579   return (true);
12580 }
12581
12582
12583 static void mixer_remove (PLCI   *plci)
12584 {
12585   DIVA_CAPI_ADAPTER   *a;
12586   PLCI   *notify_plci;
12587   dword plci_b_id;
12588   word i, j;
12589
12590   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12591     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12592     (char   *)(FILE_), __LINE__));
12593
12594   a = plci->adapter;
12595   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12596   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12597   {
12598     if ((plci->li_bchannel_id != 0)
12599      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12600     {
12601       i = a->li_base + (plci->li_bchannel_id - 1);
12602       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12603       {
12604         for (j = 0; j < li_total_channels; j++)
12605         {
12606           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12607            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12608           {
12609             notify_plci = li_config_table[j].plci;
12610             if ((notify_plci != NULL)
12611              && (notify_plci != plci)
12612              && (notify_plci->appl != NULL)
12613              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12614              && (notify_plci->State)
12615              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12616             {
12617               mixer_notify_source_removed (notify_plci, plci_b_id);
12618             }
12619           }
12620         }
12621         mixer_clear_config (plci);
12622         mixer_calculate_coefs (a);
12623         mixer_notify_update (plci, true);
12624       }
12625       li_config_table[i].plci = NULL;
12626       plci->li_bchannel_id = 0;
12627     }
12628   }
12629 }
12630
12631
12632 /*------------------------------------------------------------------*/
12633 /* Echo canceller facilities                                        */
12634 /*------------------------------------------------------------------*/
12635
12636
12637 static void ec_write_parameters (PLCI   *plci)
12638 {
12639   word w;
12640     byte parameter_buffer[6];
12641
12642   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12643     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12644     (char   *)(FILE_), __LINE__));
12645
12646   parameter_buffer[0] = 5;
12647   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12648   PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12649   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12650   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12651   PUT_WORD (&parameter_buffer[4], w);
12652   add_p (plci, FTY, parameter_buffer);
12653   sig_req (plci, TEL_CTRL, 0);
12654   send_req (plci);
12655 }
12656
12657
12658 static void ec_clear_config (PLCI   *plci)
12659 {
12660
12661   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12662     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12663     (char   *)(FILE_), __LINE__));
12664
12665   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12666     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12667   plci->ec_tail_length = 0;
12668 }
12669
12670
12671 static void ec_prepare_switch (dword Id, PLCI   *plci)
12672 {
12673
12674   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12675     UnMapId (Id), (char   *)(FILE_), __LINE__));
12676
12677 }
12678
12679
12680 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12681 {
12682
12683   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12684     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12685
12686   return (GOOD);
12687 }
12688
12689
12690 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12691 {
12692   word Info;
12693
12694   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12695     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12696
12697   Info = GOOD;
12698   if (plci->B1_facilities & B1_FACILITY_EC)
12699   {
12700     switch (plci->adjust_b_state)
12701     {
12702     case ADJUST_B_RESTORE_EC_1:
12703       plci->internal_command = plci->adjust_b_command;
12704       if (plci->sig_req)
12705       {
12706         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12707         break;
12708       }
12709       ec_write_parameters (plci);
12710       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12711       break;
12712     case ADJUST_B_RESTORE_EC_2:
12713       if ((Rc != OK) && (Rc != OK_FC))
12714       {
12715         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12716           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12717         Info = _WRONG_STATE;
12718         break;
12719       }
12720       break;
12721     }
12722   }
12723   return (Info);
12724 }
12725
12726
12727 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12728 {
12729   word internal_command, Info;
12730     byte result[8];
12731
12732   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12733     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12734     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12735
12736   Info = GOOD;
12737   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12738   {
12739     result[0] = 2;
12740     PUT_WORD (&result[1], EC_SUCCESS);
12741   }
12742   else
12743   {
12744     result[0] = 5;
12745     PUT_WORD (&result[1], plci->ec_cmd);
12746     result[3] = 2;
12747     PUT_WORD (&result[4], GOOD);
12748   }
12749   internal_command = plci->internal_command;
12750   plci->internal_command = 0;
12751   switch (plci->ec_cmd)
12752   {
12753   case EC_ENABLE_OPERATION:
12754   case EC_FREEZE_COEFFICIENTS:
12755   case EC_RESUME_COEFFICIENT_UPDATE:
12756   case EC_RESET_COEFFICIENTS:
12757     switch (internal_command)
12758     {
12759     default:
12760       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12761         B1_FACILITY_EC), EC_COMMAND_1);
12762     case EC_COMMAND_1:
12763       if (adjust_b_process (Id, plci, Rc) != GOOD)
12764       {
12765         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12766           UnMapId (Id), (char   *)(FILE_), __LINE__));
12767         Info = _FACILITY_NOT_SUPPORTED;
12768         break;
12769       }
12770       if (plci->internal_command)
12771         return;
12772     case EC_COMMAND_2:
12773       if (plci->sig_req)
12774       {
12775         plci->internal_command = EC_COMMAND_2;
12776         return;
12777       }
12778       plci->internal_command = EC_COMMAND_3;
12779       ec_write_parameters (plci);
12780       return;
12781     case EC_COMMAND_3:
12782       if ((Rc != OK) && (Rc != OK_FC))
12783       {
12784         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12785           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12786         Info = _FACILITY_NOT_SUPPORTED;
12787         break;
12788       }
12789       break;
12790     }
12791     break;
12792
12793   case EC_DISABLE_OPERATION:
12794     switch (internal_command)
12795     {
12796     default:
12797     case EC_COMMAND_1:
12798       if (plci->B1_facilities & B1_FACILITY_EC)
12799       {
12800         if (plci->sig_req)
12801         {
12802           plci->internal_command = EC_COMMAND_1;
12803           return;
12804         }
12805         plci->internal_command = EC_COMMAND_2;
12806         ec_write_parameters (plci);
12807         return;
12808       }
12809       Rc = OK;
12810     case EC_COMMAND_2:
12811       if ((Rc != OK) && (Rc != OK_FC))
12812       {
12813         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12814           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12815         Info = _FACILITY_NOT_SUPPORTED;
12816         break;
12817       }
12818       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12819         ~B1_FACILITY_EC), EC_COMMAND_3);
12820     case EC_COMMAND_3:
12821       if (adjust_b_process (Id, plci, Rc) != GOOD)
12822       {
12823         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12824           UnMapId (Id), (char   *)(FILE_), __LINE__));
12825         Info = _FACILITY_NOT_SUPPORTED;
12826         break;
12827       }
12828       if (plci->internal_command)
12829         return;
12830       break;
12831     }
12832     break;
12833   }
12834   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12835     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12836     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12837 }
12838
12839
12840 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12841 {
12842   word Info;
12843   word opt;
12844     API_PARSE ec_parms[3];
12845     byte result[16];
12846
12847   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12848     UnMapId (Id), (char   *)(FILE_), __LINE__));
12849
12850   Info = GOOD;
12851   result[0] = 0;
12852   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12853   {
12854     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12855       UnMapId (Id), (char   *)(FILE_), __LINE__));
12856     Info = _FACILITY_NOT_SUPPORTED;
12857   }
12858   else
12859   {
12860     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12861     {
12862       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12863       {
12864         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12865           UnMapId (Id), (char   *)(FILE_), __LINE__));
12866         Info = _WRONG_MESSAGE_FORMAT;
12867       }
12868       else
12869       {
12870         if (plci == NULL)
12871         {
12872           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12873             UnMapId (Id), (char   *)(FILE_), __LINE__));
12874           Info = _WRONG_IDENTIFIER;
12875         }
12876         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12877         {
12878           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12879             UnMapId (Id), (char   *)(FILE_), __LINE__));
12880           Info = _WRONG_STATE;
12881         }
12882         else
12883         {
12884           plci->command = 0;
12885           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12886           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12887           result[0] = 2;
12888           PUT_WORD (&result[1], EC_SUCCESS);
12889           if (msg[1].length >= 4)
12890           {
12891             opt = GET_WORD (&ec_parms[0].info[2]);
12892             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12893               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12894             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12895               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12896             if (opt & EC_DETECT_DISABLE_TONE)
12897               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12898             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12899               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12900             if (msg[1].length >= 6)
12901             {
12902               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12903             }
12904           }
12905           switch (plci->ec_cmd)
12906           {
12907           case EC_ENABLE_OPERATION:
12908             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12909             start_internal_command (Id, plci, ec_command);
12910             return (false);
12911
12912           case EC_DISABLE_OPERATION:
12913             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12914               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12915               LEC_RESET_COEFFICIENTS;
12916             start_internal_command (Id, plci, ec_command);
12917             return (false);
12918
12919           case EC_FREEZE_COEFFICIENTS:
12920             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12921             start_internal_command (Id, plci, ec_command);
12922             return (false);
12923
12924           case EC_RESUME_COEFFICIENT_UPDATE:
12925             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12926             start_internal_command (Id, plci, ec_command);
12927             return (false);
12928
12929           case EC_RESET_COEFFICIENTS:
12930             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12931             start_internal_command (Id, plci, ec_command);
12932             return (false);
12933
12934           default:
12935             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12936               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12937             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12938           }
12939         }
12940       }
12941     }
12942     else
12943     {
12944       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12945       {
12946         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12947           UnMapId (Id), (char   *)(FILE_), __LINE__));
12948         Info = _WRONG_MESSAGE_FORMAT;
12949       }
12950       else
12951       {
12952         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12953         {
12954           result[0] = 11;
12955           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12956           result[3] = 8;
12957           PUT_WORD (&result[4], GOOD);
12958           PUT_WORD (&result[6], 0x0007);
12959           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12960           PUT_WORD (&result[10], 0);
12961         }
12962         else if (plci == NULL)
12963         {
12964           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12965             UnMapId (Id), (char   *)(FILE_), __LINE__));
12966           Info = _WRONG_IDENTIFIER;
12967         }
12968         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12969         {
12970           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12971             UnMapId (Id), (char   *)(FILE_), __LINE__));
12972           Info = _WRONG_STATE;
12973         }
12974         else
12975         {
12976           plci->command = 0;
12977           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12978           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12979           result[0] = 5;
12980           PUT_WORD (&result[1], plci->ec_cmd);
12981           result[3] = 2;
12982           PUT_WORD (&result[4], GOOD);
12983           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12984             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12985           plci->ec_tail_length = 0;
12986           if (ec_parms[1].length >= 2)
12987           {
12988             opt = GET_WORD (&ec_parms[1].info[1]);
12989             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12990               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12991             if (opt & EC_DETECT_DISABLE_TONE)
12992               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12993             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12994               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12995             if (ec_parms[1].length >= 4)
12996             {
12997               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12998             }
12999           }
13000           switch (plci->ec_cmd)
13001           {
13002           case EC_ENABLE_OPERATION:
13003             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
13004             start_internal_command (Id, plci, ec_command);
13005             return (false);
13006
13007           case EC_DISABLE_OPERATION:
13008             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
13009               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
13010               LEC_RESET_COEFFICIENTS;
13011             start_internal_command (Id, plci, ec_command);
13012             return (false);
13013
13014           default:
13015             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
13016               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
13017             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13018           }
13019         }
13020       }
13021     }
13022   }
13023   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13024     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13025     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13026   return (false);
13027 }
13028
13029
13030 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13031 {
13032     byte result[8];
13033
13034   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13035     UnMapId (Id), (char   *)(FILE_), __LINE__));
13036
13037   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13038   {
13039     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13040     {
13041       result[0] = 2;
13042       PUT_WORD (&result[1], 0);
13043       switch (msg[1])
13044       {
13045       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13046         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13047         break;
13048       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13049         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13050         break;
13051       case LEC_DISABLE_RELEASED:
13052         PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13053         break;
13054       }
13055     }
13056     else
13057     {
13058       result[0] = 5;
13059       PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13060       result[3] = 2;
13061       PUT_WORD (&result[4], 0);
13062       switch (msg[1])
13063       {
13064       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13065         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13066         break;
13067       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13068         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13069         break;
13070       case LEC_DISABLE_RELEASED:
13071         PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13072         break;
13073       }
13074     }
13075     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13076       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13077   }
13078 }
13079
13080
13081
13082 /*------------------------------------------------------------------*/
13083 /* Advanced voice                                                   */
13084 /*------------------------------------------------------------------*/
13085
13086 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13087 {
13088   DIVA_CAPI_ADAPTER   *a;
13089   word i;
13090   byte *p;
13091
13092   word w, n, j, k;
13093   byte ch_map[MIXER_CHANNELS_BRI];
13094
13095     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13096
13097   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13098     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13099     (char   *)(FILE_), __LINE__, write_command));
13100
13101   a = plci->adapter;
13102   p = coef_buffer + 1;
13103   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13104   i = 0;
13105   while (i + sizeof(word) <= a->adv_voice_coef_length)
13106   {
13107     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13108     p += 2;
13109     i += 2;
13110   }
13111   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13112   {
13113     PUT_WORD (p, 0x8000);
13114     p += 2;
13115     i += 2;
13116   }
13117
13118   if (!a->li_pri && (plci->li_bchannel_id == 0))
13119   {
13120     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13121     {
13122       plci->li_bchannel_id = 1;
13123       li_config_table[a->li_base].plci = plci;
13124       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13125         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13126         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13127     }
13128     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13129     {
13130       plci->li_bchannel_id = 2;
13131       li_config_table[a->li_base + 1].plci = plci;
13132       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13133         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13134         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13135     }
13136   }
13137   if (!a->li_pri && (plci->li_bchannel_id != 0)
13138    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13139   {
13140     i = a->li_base + (plci->li_bchannel_id - 1);
13141     switch (write_command)
13142     {
13143     case ADV_VOICE_WRITE_ACTIVATION:
13144       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13145       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13146       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13147       {
13148         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13149         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13150       }
13151       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13152       {
13153         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13154         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13155         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13156         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13157       }
13158       mixer_calculate_coefs (a);
13159       li_config_table[i].curchnl = li_config_table[i].channel;
13160       li_config_table[j].curchnl = li_config_table[j].channel;
13161       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13162         li_config_table[k].curchnl = li_config_table[k].channel;
13163       break;
13164
13165     case ADV_VOICE_WRITE_DEACTIVATION:
13166       for (j = 0; j < li_total_channels; j++)
13167       {
13168         li_config_table[i].flag_table[j] = 0;
13169         li_config_table[j].flag_table[i] = 0;
13170       }
13171       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13172       for (j = 0; j < li_total_channels; j++)
13173       {
13174         li_config_table[k].flag_table[j] = 0;
13175         li_config_table[j].flag_table[k] = 0;
13176       }
13177       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13178       {
13179         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13180         for (j = 0; j < li_total_channels; j++)
13181         {
13182           li_config_table[k].flag_table[j] = 0;
13183           li_config_table[j].flag_table[k] = 0;
13184         }
13185       }
13186       mixer_calculate_coefs (a);
13187       break;
13188     }
13189     if (plci->B1_facilities & B1_FACILITY_MIXER)
13190     {
13191       w = 0;
13192       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13193         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13194       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13195         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13196       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13197         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13198       *(p++) = (byte) w;
13199       *(p++) = (byte)(w >> 8);
13200       for (j = 0; j < sizeof(ch_map); j += 2)
13201       {
13202         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13203         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13204       }
13205       for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13206       {
13207         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13208         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13209         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13210         {
13211           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13212           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13213           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13214         }
13215         else
13216         {
13217           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13218             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13219         }
13220       }
13221     }
13222     else
13223     {
13224       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13225         *(p++) = a->adv_voice_coef_buffer[i];
13226     }
13227   }
13228   else
13229
13230   {
13231     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13232       *(p++) = a->adv_voice_coef_buffer[i];
13233   }
13234   coef_buffer[0] = (p - coef_buffer) - 1;
13235   add_p (plci, FTY, coef_buffer);
13236   sig_req (plci, TEL_CTRL, 0);
13237   send_req (plci);
13238 }
13239
13240
13241 static void adv_voice_clear_config (PLCI   *plci)
13242 {
13243   DIVA_CAPI_ADAPTER   *a;
13244
13245   word i, j;
13246
13247
13248   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13249     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13250     (char   *)(FILE_), __LINE__));
13251
13252   a = plci->adapter;
13253   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13254   {
13255     a->adv_voice_coef_length = 0;
13256
13257     if (!a->li_pri && (plci->li_bchannel_id != 0)
13258      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13259     {
13260       i = a->li_base + (plci->li_bchannel_id - 1);
13261       li_config_table[i].curchnl = 0;
13262       li_config_table[i].channel = 0;
13263       li_config_table[i].chflags = 0;
13264       for (j = 0; j < li_total_channels; j++)
13265       {
13266         li_config_table[i].flag_table[j] = 0;
13267         li_config_table[j].flag_table[i] = 0;
13268         li_config_table[i].coef_table[j] = 0;
13269         li_config_table[j].coef_table[i] = 0;
13270       }
13271       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13272       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13273       li_config_table[i].curchnl = 0;
13274       li_config_table[i].channel = 0;
13275       li_config_table[i].chflags = 0;
13276       for (j = 0; j < li_total_channels; j++)
13277       {
13278         li_config_table[i].flag_table[j] = 0;
13279         li_config_table[j].flag_table[i] = 0;
13280         li_config_table[i].coef_table[j] = 0;
13281         li_config_table[j].coef_table[i] = 0;
13282       }
13283       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13284       {
13285         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13286         li_config_table[i].curchnl = 0;
13287         li_config_table[i].channel = 0;
13288         li_config_table[i].chflags = 0;
13289         for (j = 0; j < li_total_channels; j++)
13290         {
13291           li_config_table[i].flag_table[j] = 0;
13292           li_config_table[j].flag_table[i] = 0;
13293           li_config_table[i].coef_table[j] = 0;
13294           li_config_table[j].coef_table[i] = 0;
13295         }
13296       }
13297     }
13298
13299   }
13300 }
13301
13302
13303 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13304 {
13305
13306   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13307     UnMapId (Id), (char   *)(FILE_), __LINE__));
13308
13309 }
13310
13311
13312 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13313 {
13314
13315   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13316     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13317
13318   return (GOOD);
13319 }
13320
13321
13322 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13323 {
13324   DIVA_CAPI_ADAPTER   *a;
13325   word Info;
13326
13327   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13328     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13329
13330   Info = GOOD;
13331   a = plci->adapter;
13332   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13333    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13334   {
13335     switch (plci->adjust_b_state)
13336     {
13337     case ADJUST_B_RESTORE_VOICE_1:
13338       plci->internal_command = plci->adjust_b_command;
13339       if (plci->sig_req)
13340       {
13341         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13342         break;
13343       }
13344       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13345       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13346       break;
13347     case ADJUST_B_RESTORE_VOICE_2:
13348       if ((Rc != OK) && (Rc != OK_FC))
13349       {
13350         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13351           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13352         Info = _WRONG_STATE;
13353         break;
13354       }
13355       break;
13356     }
13357   }
13358   return (Info);
13359 }
13360
13361
13362
13363
13364 /*------------------------------------------------------------------*/
13365 /* B1 resource switching                                            */
13366 /*------------------------------------------------------------------*/
13367
13368 static byte b1_facilities_table[] =
13369 {
13370   0x00,  /* 0  No bchannel resources      */
13371   0x00,  /* 1  Codec (automatic law)      */
13372   0x00,  /* 2  Codec (A-law)              */
13373   0x00,  /* 3  Codec (y-law)              */
13374   0x00,  /* 4  HDLC for X.21              */
13375   0x00,  /* 5  HDLC                       */
13376   0x00,  /* 6  External Device 0          */
13377   0x00,  /* 7  External Device 1          */
13378   0x00,  /* 8  HDLC 56k                   */
13379   0x00,  /* 9  Transparent                */
13380   0x00,  /* 10 Loopback to network        */
13381   0x00,  /* 11 Test pattern to net        */
13382   0x00,  /* 12 Rate adaptation sync       */
13383   0x00,  /* 13 Rate adaptation async      */
13384   0x00,  /* 14 R-Interface                */
13385   0x00,  /* 15 HDLC 128k leased line      */
13386   0x00,  /* 16 FAX                        */
13387   0x00,  /* 17 Modem async                */
13388   0x00,  /* 18 Modem sync HDLC            */
13389   0x00,  /* 19 V.110 async HDLC           */
13390   0x12,  /* 20 Adv voice (Trans,mixer)    */
13391   0x00,  /* 21 Codec connected to IC      */
13392   0x0c,  /* 22 Trans,DTMF                 */
13393   0x1e,  /* 23 Trans,DTMF+mixer           */
13394   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13395   0x13,  /* 25 Trans,mixer+local          */
13396   0x12,  /* 26 HDLC,mixer                 */
13397   0x12,  /* 27 HDLC 56k,mixer             */
13398   0x2c,  /* 28 Trans,LEC+DTMF             */
13399   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13400   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13401   0x2c,  /* 31 RTP,LEC+DTMF               */
13402   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13403   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13404   0x00,  /* 34 Signaling task             */
13405   0x00,  /* 35 PIAFS                      */
13406   0x0c,  /* 36 Trans,DTMF+TONE            */
13407   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13408   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13409 };
13410
13411
13412 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13413 {
13414   word b1_facilities;
13415
13416   b1_facilities = b1_facilities_table[b1_resource];
13417   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13418   {
13419
13420     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13421        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13422
13423     {
13424       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13425         b1_facilities |= B1_FACILITY_DTMFX;
13426       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13427         b1_facilities |= B1_FACILITY_DTMFR;
13428     }
13429   }
13430   if ((b1_resource == 17) || (b1_resource == 18))
13431   {
13432     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13433       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13434   }
13435 /*
13436   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13437     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13438     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13439 */
13440   return (b1_facilities);
13441 }
13442
13443
13444 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13445 {
13446   byte b;
13447
13448   switch (b1_resource)
13449   {
13450   case 5:
13451   case 26:
13452     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13453       b = 26;
13454     else
13455       b = 5;
13456     break;
13457
13458   case 8:
13459   case 27:
13460     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13461       b = 27;
13462     else
13463       b = 8;
13464     break;
13465
13466   case 9:
13467   case 20:
13468   case 22:
13469   case 23:
13470   case 24:
13471   case 25:
13472   case 28:
13473   case 29:
13474   case 30:
13475   case 36:
13476   case 37:
13477   case 38:
13478     if (b1_facilities & B1_FACILITY_EC)
13479     {
13480       if (b1_facilities & B1_FACILITY_LOCAL)
13481         b = 30;
13482       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13483         b = 29;
13484       else
13485         b = 28;
13486     }
13487
13488     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13489       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13490        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13491     {
13492       if (b1_facilities & B1_FACILITY_LOCAL)
13493         b = 38;
13494       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13495         b = 37;
13496       else
13497         b = 36;
13498     }
13499
13500     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13501       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13502      || ((b1_facilities & B1_FACILITY_DTMFR)
13503       && ((b1_facilities & B1_FACILITY_MIXER)
13504        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13505      || ((b1_facilities & B1_FACILITY_DTMFX)
13506       && ((b1_facilities & B1_FACILITY_MIXER)
13507        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13508     {
13509       if (b1_facilities & B1_FACILITY_LOCAL)
13510         b = 24;
13511       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13512         b = 23;
13513       else
13514         b = 22;
13515     }
13516     else
13517     {
13518       if (b1_facilities & B1_FACILITY_LOCAL)
13519         b = 25;
13520       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13521         b = 20;
13522       else
13523         b = 9;
13524     }
13525     break;
13526
13527   case 31:
13528   case 32:
13529   case 33:
13530     if (b1_facilities & B1_FACILITY_LOCAL)
13531       b = 33;
13532     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13533       b = 32;
13534     else
13535       b = 31;
13536     break;
13537
13538   default:
13539     b = b1_resource;
13540   }
13541   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13542     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13543     (char   *)(FILE_), __LINE__,
13544     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13545   return (b);
13546 }
13547
13548
13549 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13550 {
13551   word removed_facilities;
13552
13553   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13554     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13555     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13556     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13557
13558   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13559   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13560
13561   if (removed_facilities & B1_FACILITY_EC)
13562     ec_clear_config (plci);
13563
13564
13565   if (removed_facilities & B1_FACILITY_DTMFR)
13566   {
13567     dtmf_rec_clear_config (plci);
13568     dtmf_parameter_clear_config (plci);
13569   }
13570   if (removed_facilities & B1_FACILITY_DTMFX)
13571     dtmf_send_clear_config (plci);
13572
13573
13574   if (removed_facilities & B1_FACILITY_MIXER)
13575     mixer_clear_config (plci);
13576
13577   if (removed_facilities & B1_FACILITY_VOICE)
13578     adv_voice_clear_config (plci);
13579   plci->B1_facilities = new_b1_facilities;
13580 }
13581
13582
13583 static void adjust_b_clear (PLCI   *plci)
13584 {
13585
13586   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13587     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13588     (char   *)(FILE_), __LINE__));
13589
13590   plci->adjust_b_restore = false;
13591 }
13592
13593
13594 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13595 {
13596   word Info;
13597   byte b1_resource;
13598   NCCI   * ncci_ptr;
13599     API_PARSE bp[2];
13600
13601   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13602     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13603
13604   Info = GOOD;
13605   switch (plci->adjust_b_state)
13606   {
13607   case ADJUST_B_START:
13608     if ((plci->adjust_b_parms_msg == NULL)
13609      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13610      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13611       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13612     {
13613       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13614         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13615       if (b1_resource == plci->B1_resource)
13616       {
13617         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13618         break;
13619       }
13620       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13621       {
13622         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13623           UnMapId (Id), (char   *)(FILE_), __LINE__,
13624           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13625         Info = _WRONG_STATE;
13626         break;
13627       }
13628     }
13629     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13630     {
13631
13632       mixer_prepare_switch (Id, plci);
13633
13634
13635       dtmf_prepare_switch (Id, plci);
13636       dtmf_parameter_prepare_switch (Id, plci);
13637
13638
13639       ec_prepare_switch (Id, plci);
13640
13641       adv_voice_prepare_switch (Id, plci);
13642     }
13643     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13644     Rc = OK;
13645   case ADJUST_B_SAVE_MIXER_1:
13646     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13647     {
13648
13649       Info = mixer_save_config (Id, plci, Rc);
13650       if ((Info != GOOD) || plci->internal_command)
13651         break;
13652
13653     }
13654     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13655     Rc = OK;
13656   case ADJUST_B_SAVE_DTMF_1:
13657     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13658     {
13659
13660       Info = dtmf_save_config (Id, plci, Rc);
13661       if ((Info != GOOD) || plci->internal_command)
13662         break;
13663
13664     }
13665     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13666   case ADJUST_B_REMOVE_L23_1:
13667     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13668      && plci->NL.Id && !plci->nl_remove_id)
13669     {
13670       plci->internal_command = plci->adjust_b_command;
13671       if (plci->adjust_b_ncci != 0)
13672       {
13673         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13674         while (ncci_ptr->data_pending)
13675         {
13676           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13677           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13678         }
13679         while (ncci_ptr->data_ack_pending)
13680           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13681       }
13682       nl_req_ncci (plci, REMOVE,
13683         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13684       send_req (plci);
13685       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13686       break;
13687     }
13688     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13689     Rc = OK;
13690   case ADJUST_B_REMOVE_L23_2:
13691     if ((Rc != OK) && (Rc != OK_FC))
13692     {
13693       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13694         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13695       Info = _WRONG_STATE;
13696       break;
13697     }
13698     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13699     {
13700       if (plci_nl_busy (plci))
13701       {
13702         plci->internal_command = plci->adjust_b_command;
13703         break;
13704       }
13705     }
13706     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13707     Rc = OK;
13708   case ADJUST_B_SAVE_EC_1:
13709     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13710     {
13711
13712       Info = ec_save_config (Id, plci, Rc);
13713       if ((Info != GOOD) || plci->internal_command)
13714         break;
13715
13716     }
13717     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13718     Rc = OK;
13719   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13720     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13721     {
13722
13723       Info = dtmf_parameter_save_config (Id, plci, Rc);
13724       if ((Info != GOOD) || plci->internal_command)
13725         break;
13726
13727     }
13728     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13729     Rc = OK;
13730   case ADJUST_B_SAVE_VOICE_1:
13731     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13732     {
13733       Info = adv_voice_save_config (Id, plci, Rc);
13734       if ((Info != GOOD) || plci->internal_command)
13735         break;
13736     }
13737     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13738   case ADJUST_B_SWITCH_L1_1:
13739     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13740     {
13741       if (plci->sig_req)
13742       {
13743         plci->internal_command = plci->adjust_b_command;
13744         break;
13745       }
13746       if (plci->adjust_b_parms_msg != NULL)
13747         api_load_msg (plci->adjust_b_parms_msg, bp);
13748       else
13749         api_load_msg (&plci->B_protocol, bp);
13750       Info = add_b1 (plci, bp,
13751         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13752         plci->adjust_b_facilities);
13753       if (Info != GOOD)
13754       {
13755         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13756           UnMapId (Id), (char   *)(FILE_), __LINE__,
13757           plci->B1_resource, plci->adjust_b_facilities));
13758         break;
13759       }
13760       plci->internal_command = plci->adjust_b_command;
13761       sig_req (plci, RESOURCES, 0);
13762       send_req (plci);
13763       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13764       break;
13765     }
13766     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13767     Rc = OK;
13768   case ADJUST_B_SWITCH_L1_2:
13769     if ((Rc != OK) && (Rc != OK_FC))
13770     {
13771       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13772         UnMapId (Id), (char   *)(FILE_), __LINE__,
13773         Rc, plci->B1_resource, plci->adjust_b_facilities));
13774       Info = _WRONG_STATE;
13775       break;
13776     }
13777     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13778     Rc = OK;
13779   case ADJUST_B_RESTORE_VOICE_1:
13780   case ADJUST_B_RESTORE_VOICE_2:
13781     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13782     {
13783       Info = adv_voice_restore_config (Id, plci, Rc);
13784       if ((Info != GOOD) || plci->internal_command)
13785         break;
13786     }
13787     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13788     Rc = OK;
13789   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13790   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13791     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13792     {
13793
13794       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13795       if ((Info != GOOD) || plci->internal_command)
13796         break;
13797
13798     }
13799     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13800     Rc = OK;
13801   case ADJUST_B_RESTORE_EC_1:
13802   case ADJUST_B_RESTORE_EC_2:
13803     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13804     {
13805
13806       Info = ec_restore_config (Id, plci, Rc);
13807       if ((Info != GOOD) || plci->internal_command)
13808         break;
13809
13810     }
13811     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13812   case ADJUST_B_ASSIGN_L23_1:
13813     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13814     {
13815       if (plci_nl_busy (plci))
13816       {
13817         plci->internal_command = plci->adjust_b_command;
13818         break;
13819       }
13820       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13821         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13822       if (plci->adjust_b_parms_msg != NULL)
13823         api_load_msg (plci->adjust_b_parms_msg, bp);
13824       else
13825         api_load_msg (&plci->B_protocol, bp);
13826       Info = add_b23 (plci, bp);
13827       if (Info != GOOD)
13828       {
13829         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13830           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13831         break;
13832       }
13833       plci->internal_command = plci->adjust_b_command;
13834       nl_req_ncci (plci, ASSIGN, 0);
13835       send_req (plci);
13836       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13837       break;
13838     }
13839     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13840     Rc = ASSIGN_OK;
13841   case ADJUST_B_ASSIGN_L23_2:
13842     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13843     {
13844       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13845         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13846       Info = _WRONG_STATE;
13847       break;
13848     }
13849     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13850     {
13851       if (Rc != ASSIGN_OK)
13852       {
13853         plci->internal_command = plci->adjust_b_command;
13854         break;
13855       }
13856     }
13857     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13858     {
13859       plci->adjust_b_restore = true;
13860       break;
13861     }
13862     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13863   case ADJUST_B_CONNECT_1:
13864     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13865     {
13866       plci->internal_command = plci->adjust_b_command;
13867       if (plci_nl_busy (plci))
13868         break;
13869       nl_req_ncci (plci, N_CONNECT, 0);
13870       send_req (plci);
13871       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13872       break;
13873     }
13874     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13875     Rc = OK;
13876   case ADJUST_B_CONNECT_2:
13877   case ADJUST_B_CONNECT_3:
13878   case ADJUST_B_CONNECT_4:
13879     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13880     {
13881       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13882         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13883       Info = _WRONG_STATE;
13884       break;
13885     }
13886     if (Rc == OK)
13887     {
13888       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13889       {
13890         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13891         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13892       }
13893       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13894         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13895       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13896         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13897     }
13898     else if (Rc == 0)
13899     {
13900       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13901         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13902       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13903         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13904     }
13905     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13906     {
13907       plci->internal_command = plci->adjust_b_command;
13908       break;
13909     }
13910     Rc = OK;
13911   case ADJUST_B_RESTORE_DTMF_1:
13912   case ADJUST_B_RESTORE_DTMF_2:
13913     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13914     {
13915
13916       Info = dtmf_restore_config (Id, plci, Rc);
13917       if ((Info != GOOD) || plci->internal_command)
13918         break;
13919
13920     }
13921     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13922     Rc = OK;
13923   case ADJUST_B_RESTORE_MIXER_1:
13924   case ADJUST_B_RESTORE_MIXER_2:
13925   case ADJUST_B_RESTORE_MIXER_3:
13926   case ADJUST_B_RESTORE_MIXER_4:
13927   case ADJUST_B_RESTORE_MIXER_5:
13928   case ADJUST_B_RESTORE_MIXER_6:
13929   case ADJUST_B_RESTORE_MIXER_7:
13930     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13931     {
13932
13933       Info = mixer_restore_config (Id, plci, Rc);
13934       if ((Info != GOOD) || plci->internal_command)
13935         break;
13936
13937     }
13938     plci->adjust_b_state = ADJUST_B_END;
13939   case ADJUST_B_END:
13940     break;
13941   }
13942   return (Info);
13943 }
13944
13945
13946 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13947 {
13948
13949   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13950     UnMapId (Id), (char   *)(FILE_), __LINE__,
13951     plci->B1_resource, b1_facilities));
13952
13953   plci->adjust_b_parms_msg = bp_msg;
13954   plci->adjust_b_facilities = b1_facilities;
13955   plci->adjust_b_command = internal_command;
13956   plci->adjust_b_ncci = (word)(Id >> 16);
13957   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13958     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13959   else
13960     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13961   plci->adjust_b_state = ADJUST_B_START;
13962   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13963     UnMapId (Id), (char   *)(FILE_), __LINE__,
13964     plci->B1_resource, b1_facilities));
13965 }
13966
13967
13968 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13969 {
13970   word internal_command;
13971
13972   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13973     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13974
13975   internal_command = plci->internal_command;
13976   plci->internal_command = 0;
13977   switch (internal_command)
13978   {
13979   default:
13980     plci->command = 0;
13981     if (plci->req_in != 0)
13982     {
13983       plci->internal_command = ADJUST_B_RESTORE_1;
13984       break;
13985     }
13986     Rc = OK;
13987   case ADJUST_B_RESTORE_1:
13988     if ((Rc != OK) && (Rc != OK_FC))
13989     {
13990       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13991         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13992     }
13993     plci->adjust_b_parms_msg = NULL;
13994     plci->adjust_b_facilities = plci->B1_facilities;
13995     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13996     plci->adjust_b_ncci = (word)(Id >> 16);
13997     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13998     plci->adjust_b_state = ADJUST_B_START;
13999     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
14000       UnMapId (Id), (char   *)(FILE_), __LINE__));
14001   case ADJUST_B_RESTORE_2:
14002     if (adjust_b_process (Id, plci, Rc) != GOOD)
14003     {
14004       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
14005         UnMapId (Id), (char   *)(FILE_), __LINE__));
14006     }
14007     if (plci->internal_command)
14008       break;
14009     break;
14010   }
14011 }
14012
14013
14014 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
14015 {
14016   word Info;
14017   word internal_command;
14018
14019   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14020     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14021
14022   Info = GOOD;
14023   internal_command = plci->internal_command;
14024   plci->internal_command = 0;
14025   switch (internal_command)
14026   {
14027   default:
14028     plci->command = 0;
14029     plci->adjust_b_parms_msg = NULL;
14030     plci->adjust_b_facilities = plci->B1_facilities;
14031     plci->adjust_b_command = RESET_B3_COMMAND_1;
14032     plci->adjust_b_ncci = (word)(Id >> 16);
14033     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14034     plci->adjust_b_state = ADJUST_B_START;
14035     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14036       UnMapId (Id), (char   *)(FILE_), __LINE__));
14037   case RESET_B3_COMMAND_1:
14038     Info = adjust_b_process (Id, plci, Rc);
14039     if (Info != GOOD)
14040     {
14041       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14042         UnMapId (Id), (char   *)(FILE_), __LINE__));
14043       break;
14044     }
14045     if (plci->internal_command)
14046       return;
14047     break;
14048   }
14049 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14050   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14051 }
14052
14053
14054 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14055 {
14056   word Info;
14057   word internal_command;
14058   byte esc_chi[3];
14059
14060   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14061     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14062
14063   Info = GOOD;
14064   internal_command = plci->internal_command;
14065   plci->internal_command = 0;
14066   switch (internal_command)
14067   {
14068   default:
14069     plci->command = 0;
14070     plci->adjust_b_parms_msg = &plci->saved_msg;
14071     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14072       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14073     else
14074       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14075     plci->adjust_b_command = SELECT_B_COMMAND_1;
14076     plci->adjust_b_ncci = (word)(Id >> 16);
14077     if (plci->saved_msg.parms[0].length == 0)
14078     {
14079       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14080         ADJUST_B_MODE_NO_RESOURCE;
14081     }
14082     else
14083     {
14084       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14085         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14086     }
14087     plci->adjust_b_state = ADJUST_B_START;
14088     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14089       UnMapId (Id), (char   *)(FILE_), __LINE__));
14090   case SELECT_B_COMMAND_1:
14091     Info = adjust_b_process (Id, plci, Rc);
14092     if (Info != GOOD)
14093     {
14094       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14095         UnMapId (Id), (char   *)(FILE_), __LINE__));
14096       break;
14097     }
14098     if (plci->internal_command)
14099       return;
14100     if (plci->tel == ADV_VOICE)
14101     {
14102       esc_chi[0] = 0x02;
14103       esc_chi[1] = 0x18;
14104       esc_chi[2] = plci->b_channel;
14105       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14106     }
14107     break;
14108   }
14109   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14110 }
14111
14112
14113 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14114 {
14115   word Info;
14116   word internal_command;
14117
14118   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14119     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14120
14121   Info = GOOD;
14122   internal_command = plci->internal_command;
14123   plci->internal_command = 0;
14124   switch (internal_command)
14125   {
14126   default:
14127     plci->command = 0;
14128   case FAX_CONNECT_ACK_COMMAND_1:
14129     if (plci_nl_busy (plci))
14130     {
14131       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14132       return;
14133     }
14134     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14135     plci->NData[0].P = plci->fax_connect_info_buffer;
14136     plci->NData[0].PLength = plci->fax_connect_info_length;
14137     plci->NL.X = plci->NData;
14138     plci->NL.ReqCh = 0;
14139     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14140     plci->adapter->request (&plci->NL);
14141     return;
14142   case FAX_CONNECT_ACK_COMMAND_2:
14143     if ((Rc != OK) && (Rc != OK_FC))
14144     {
14145       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14146         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14147       break;
14148     }
14149   }
14150   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14151    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14152   {
14153     if (plci->B3_prot == 4)
14154       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14155     else
14156       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14157     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14158   }
14159 }
14160
14161
14162 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14163 {
14164   word Info;
14165   word internal_command;
14166
14167   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14168     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14169
14170   Info = GOOD;
14171   internal_command = plci->internal_command;
14172   plci->internal_command = 0;
14173   switch (internal_command)
14174   {
14175   default:
14176     plci->command = 0;
14177   case FAX_EDATA_ACK_COMMAND_1:
14178     if (plci_nl_busy (plci))
14179     {
14180       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14181       return;
14182     }
14183     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14184     plci->NData[0].P = plci->fax_connect_info_buffer;
14185     plci->NData[0].PLength = plci->fax_edata_ack_length;
14186     plci->NL.X = plci->NData;
14187     plci->NL.ReqCh = 0;
14188     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14189     plci->adapter->request (&plci->NL);
14190     return;
14191   case FAX_EDATA_ACK_COMMAND_2:
14192     if ((Rc != OK) && (Rc != OK_FC))
14193     {
14194       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14195         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14196       break;
14197     }
14198   }
14199 }
14200
14201
14202 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14203 {
14204   word Info;
14205   word internal_command;
14206
14207   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14208     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14209
14210   Info = GOOD;
14211   internal_command = plci->internal_command;
14212   plci->internal_command = 0;
14213   switch (internal_command)
14214   {
14215   default:
14216     plci->command = 0;
14217   case FAX_CONNECT_INFO_COMMAND_1:
14218     if (plci_nl_busy (plci))
14219     {
14220       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14221       return;
14222     }
14223     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14224     plci->NData[0].P = plci->fax_connect_info_buffer;
14225     plci->NData[0].PLength = plci->fax_connect_info_length;
14226     plci->NL.X = plci->NData;
14227     plci->NL.ReqCh = 0;
14228     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14229     plci->adapter->request (&plci->NL);
14230     return;
14231   case FAX_CONNECT_INFO_COMMAND_2:
14232     if ((Rc != OK) && (Rc != OK_FC))
14233     {
14234       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14235         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14236       Info = _WRONG_STATE;
14237       break;
14238     }
14239     if (plci_nl_busy (plci))
14240     {
14241       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14242       return;
14243     }
14244     plci->command = _CONNECT_B3_R;
14245     nl_req_ncci (plci, N_CONNECT, 0);
14246     send_req (plci);
14247     return;
14248   }
14249   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14250 }
14251
14252
14253 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14254 {
14255   word Info;
14256   word internal_command;
14257
14258   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14259     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14260
14261   Info = GOOD;
14262   internal_command = plci->internal_command;
14263   plci->internal_command = 0;
14264   switch (internal_command)
14265   {
14266   default:
14267     plci->command = 0;
14268     plci->adjust_b_parms_msg = NULL;
14269     plci->adjust_b_facilities = plci->B1_facilities;
14270     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14271     plci->adjust_b_ncci = (word)(Id >> 16);
14272     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14273     plci->adjust_b_state = ADJUST_B_START;
14274     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14275       UnMapId (Id), (char   *)(FILE_), __LINE__));
14276   case FAX_ADJUST_B23_COMMAND_1:
14277     Info = adjust_b_process (Id, plci, Rc);
14278     if (Info != GOOD)
14279     {
14280       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14281         UnMapId (Id), (char   *)(FILE_), __LINE__));
14282       break;
14283     }
14284     if (plci->internal_command)
14285       return;
14286   case FAX_ADJUST_B23_COMMAND_2:
14287     if (plci_nl_busy (plci))
14288     {
14289       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14290       return;
14291     }
14292     plci->command = _CONNECT_B3_R;
14293     nl_req_ncci (plci, N_CONNECT, 0);
14294     send_req (plci);
14295     return;
14296   }
14297   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14298 }
14299
14300
14301 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14302 {
14303   word internal_command;
14304
14305   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14306     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14307
14308   internal_command = plci->internal_command;
14309   plci->internal_command = 0;
14310   switch (internal_command)
14311   {
14312   default:
14313     plci->command = 0;
14314     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14315     return;
14316   case FAX_DISCONNECT_COMMAND_1:
14317   case FAX_DISCONNECT_COMMAND_2:
14318   case FAX_DISCONNECT_COMMAND_3:
14319     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14320     {
14321       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14322         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14323       break;
14324     }
14325     if (Rc == OK)
14326     {
14327       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14328        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14329       {
14330         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14331       }
14332     }
14333     else if (Rc == 0)
14334     {
14335       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14336         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14337     }
14338     return;
14339   }
14340 }
14341
14342
14343
14344 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14345 {
14346   word Info;
14347   word internal_command;
14348
14349   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14350     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14351
14352   Info = GOOD;
14353   internal_command = plci->internal_command;
14354   plci->internal_command = 0;
14355   switch (internal_command)
14356   {
14357   default:
14358     plci->command = 0;
14359   case RTP_CONNECT_B3_REQ_COMMAND_1:
14360     if (plci_nl_busy (plci))
14361     {
14362       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14363       return;
14364     }
14365     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14366     nl_req_ncci (plci, N_CONNECT, 0);
14367     send_req (plci);
14368     return;
14369   case RTP_CONNECT_B3_REQ_COMMAND_2:
14370     if ((Rc != OK) && (Rc != OK_FC))
14371     {
14372       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14373         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14374       Info = _WRONG_STATE;
14375       break;
14376     }
14377     if (plci_nl_busy (plci))
14378     {
14379       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14380       return;
14381     }
14382     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14383     plci->NData[0].PLength = plci->internal_req_buffer[0];
14384     plci->NData[0].P = plci->internal_req_buffer + 1;
14385     plci->NL.X = plci->NData;
14386     plci->NL.ReqCh = 0;
14387     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14388     plci->adapter->request (&plci->NL);
14389     break;
14390   case RTP_CONNECT_B3_REQ_COMMAND_3:
14391     return;
14392   }
14393   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14394 }
14395
14396
14397 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14398 {
14399   word Info;
14400   word internal_command;
14401
14402   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14403     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14404
14405   Info = GOOD;
14406   internal_command = plci->internal_command;
14407   plci->internal_command = 0;
14408   switch (internal_command)
14409   {
14410   default:
14411     plci->command = 0;
14412   case RTP_CONNECT_B3_RES_COMMAND_1:
14413     if (plci_nl_busy (plci))
14414     {
14415       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14416       return;
14417     }
14418     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14419     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14420     send_req (plci);
14421     return;
14422   case RTP_CONNECT_B3_RES_COMMAND_2:
14423     if ((Rc != OK) && (Rc != OK_FC))
14424     {
14425       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14426         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14427       Info = _WRONG_STATE;
14428       break;
14429     }
14430     if (plci_nl_busy (plci))
14431     {
14432       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14433       return;
14434     }
14435     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14436     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14437     plci->NData[0].PLength = plci->internal_req_buffer[0];
14438     plci->NData[0].P = plci->internal_req_buffer + 1;
14439     plci->NL.X = plci->NData;
14440     plci->NL.ReqCh = 0;
14441     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14442     plci->adapter->request (&plci->NL);
14443     return;
14444   case RTP_CONNECT_B3_RES_COMMAND_3:
14445     return;
14446   }
14447 }
14448
14449
14450
14451 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14452 {
14453     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14454   word Info;
14455   word internal_command;
14456
14457   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14458     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14459
14460   Info = GOOD;
14461   internal_command = plci->internal_command;
14462   plci->internal_command = 0;
14463   switch (internal_command)
14464   {
14465   default:
14466     if (!plci->NL.Id)
14467       break;
14468     plci->command = 0;
14469     plci->adjust_b_parms_msg = NULL;
14470     plci->adjust_b_facilities = plci->B1_facilities;
14471     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14472     plci->adjust_b_ncci = (word)(Id >> 16);
14473     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14474     plci->adjust_b_state = ADJUST_B_START;
14475     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14476       UnMapId (Id), (char   *)(FILE_), __LINE__));
14477   case HOLD_SAVE_COMMAND_1:
14478     Info = adjust_b_process (Id, plci, Rc);
14479     if (Info != GOOD)
14480     {
14481       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14482         UnMapId (Id), (char   *)(FILE_), __LINE__));
14483       break;
14484     }
14485     if (plci->internal_command)
14486       return;
14487   }
14488   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14489 }
14490
14491
14492 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14493 {
14494     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14495   word Info;
14496   word internal_command;
14497
14498   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14499     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14500
14501   Info = GOOD;
14502   internal_command = plci->internal_command;
14503   plci->internal_command = 0;
14504   switch (internal_command)
14505   {
14506   default:
14507     plci->command = 0;
14508     plci->adjust_b_parms_msg = NULL;
14509     plci->adjust_b_facilities = plci->B1_facilities;
14510     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14511     plci->adjust_b_ncci = (word)(Id >> 16);
14512     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14513     plci->adjust_b_state = ADJUST_B_START;
14514     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14515       UnMapId (Id), (char   *)(FILE_), __LINE__));
14516   case RETRIEVE_RESTORE_COMMAND_1:
14517     Info = adjust_b_process (Id, plci, Rc);
14518     if (Info != GOOD)
14519     {
14520       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14521         UnMapId (Id), (char   *)(FILE_), __LINE__));
14522       break;
14523     }
14524     if (plci->internal_command)
14525       return;
14526   }
14527   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14528 }
14529
14530
14531 static void init_b1_config (PLCI   *plci)
14532 {
14533
14534   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14535     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14536     (char   *)(FILE_), __LINE__));
14537
14538   plci->B1_resource = 0;
14539   plci->B1_facilities = 0;
14540
14541   plci->li_bchannel_id = 0;
14542   mixer_clear_config (plci);
14543
14544
14545   ec_clear_config (plci);
14546
14547
14548   dtmf_rec_clear_config (plci);
14549   dtmf_send_clear_config (plci);
14550   dtmf_parameter_clear_config (plci);
14551
14552   adv_voice_clear_config (plci);
14553   adjust_b_clear (plci);
14554 }
14555
14556
14557 static void clear_b1_config (PLCI   *plci)
14558 {
14559
14560   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14561     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14562     (char   *)(FILE_), __LINE__));
14563
14564   adv_voice_clear_config (plci);
14565   adjust_b_clear (plci);
14566
14567   ec_clear_config (plci);
14568
14569
14570   dtmf_rec_clear_config (plci);
14571   dtmf_send_clear_config (plci);
14572   dtmf_parameter_clear_config (plci);
14573
14574
14575   if ((plci->li_bchannel_id != 0)
14576    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14577   {
14578     mixer_clear_config (plci);
14579     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14580     plci->li_bchannel_id = 0;
14581   }
14582
14583   plci->B1_resource = 0;
14584   plci->B1_facilities = 0;
14585 }
14586
14587
14588 /* -----------------------------------------------------------------
14589                 XON protocol local helpers
14590    ----------------------------------------------------------------- */
14591 static void channel_flow_control_remove (PLCI   * plci) {
14592   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14593   word i;
14594   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14595     if (a->ch_flow_plci[i] == plci->Id) {
14596       a->ch_flow_plci[i] = 0;
14597       a->ch_flow_control[i] = 0;
14598     }
14599   }
14600 }
14601
14602 static void channel_x_on (PLCI   * plci, byte ch) {
14603   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14604   if (a->ch_flow_control[ch] & N_XON_SENT) {
14605     a->ch_flow_control[ch] &= ~N_XON_SENT;
14606   }
14607 }
14608
14609 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14610   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14611   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14612     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14613     a->ch_flow_plci[ch] = plci->Id;
14614     a->ch_flow_control_pending++;
14615   }
14616 }
14617
14618 static void channel_request_xon (PLCI   * plci, byte ch) {
14619   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14620
14621   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14622     a->ch_flow_control[ch] |= N_XON_REQ;
14623     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14624     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14625   }
14626 }
14627
14628 static void channel_xmit_extended_xon (PLCI   * plci) {
14629   DIVA_CAPI_ADAPTER   * a;
14630   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14631   int i, one_requested = 0;
14632
14633   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14634     return;
14635   }
14636
14637   for (i = 0; i < max_ch; i++) {
14638     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14639         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14640         (plci->Id == a->ch_flow_plci[i])) {
14641       channel_request_xon (plci, (byte)i);
14642       one_requested = 1;
14643     }
14644   }
14645
14646   if (one_requested) {
14647     channel_xmit_xon (plci);
14648   }
14649 }
14650
14651 /*
14652   Try to xmit next X_ON
14653   */
14654 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14655   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14656   int i;
14657
14658   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14659     return (0);
14660   }
14661
14662   if (a->last_flow_control_ch >= max_ch) {
14663     a->last_flow_control_ch = 1;
14664   }
14665   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14666     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14667         (plci->Id == a->ch_flow_plci[i])) {
14668       a->last_flow_control_ch = i+1;
14669       return (i);
14670     }
14671   }
14672
14673   for (i = 1; i < a->last_flow_control_ch; i++) {
14674     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14675         (plci->Id == a->ch_flow_plci[i])) {
14676       a->last_flow_control_ch = i+1;
14677       return (i);
14678     }
14679   }
14680
14681   return (0);
14682 }
14683
14684 static void channel_xmit_xon (PLCI   * plci) {
14685   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14686   byte ch;
14687
14688   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14689     return;
14690   }
14691   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14692     return;
14693   }
14694   a->ch_flow_control[ch] &= ~N_XON_REQ;
14695   a->ch_flow_control[ch] |= N_XON_SENT;
14696
14697   plci->NL.Req = plci->nl_req = (byte)N_XON;
14698   plci->NL.ReqCh         = ch;
14699   plci->NL.X             = plci->NData;
14700   plci->NL.XNum          = 1;
14701   plci->NData[0].P       = &plci->RBuffer[0];
14702   plci->NData[0].PLength = 0;
14703
14704   plci->adapter->request(&plci->NL);
14705 }
14706
14707 static int channel_can_xon (PLCI   * plci, byte ch) {
14708   APPL   * APPLptr;
14709   DIVA_CAPI_ADAPTER   * a;
14710   word NCCIcode;
14711   dword count;
14712   word Num;
14713   word i;
14714
14715   APPLptr = plci->appl;
14716   a = plci->adapter;
14717
14718   if (!APPLptr)
14719     return (0);
14720
14721   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14722
14723                 /* count all buffers within the Application pool    */
14724                 /* belonging to the same NCCI. XON if a first is    */
14725                 /* used.                                            */
14726   count = 0;
14727   Num = 0xffff;
14728   for(i=0; i<APPLptr->MaxBuffer; i++) {
14729     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14730     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14731   }
14732   if ((count > 2) || (Num == 0xffff)) {
14733     return (0);
14734   }
14735   return (1);
14736 }
14737
14738
14739 /*------------------------------------------------------------------*/
14740
14741 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14742 {
14743   return 1;
14744 }
14745
14746
14747
14748 /**********************************************************************************/
14749 /* function groups the listening applications according to the CIP mask and the   */
14750 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14751 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14752 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14753 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14754 /* OS specific part (per adapter).                                                */
14755 /**********************************************************************************/
14756 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14757 {
14758   word i,j,k,busy,group_found;
14759   dword info_mask_group[MAX_CIP_TYPES];
14760   dword cip_mask_group[MAX_CIP_TYPES];
14761   word appl_number_group_type[MAX_APPL];
14762   PLCI   *auxplci;
14763
14764   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14765
14766   if(!a->group_optimization_enabled)
14767   {
14768     dbug(1,dprintf("No group optimization"));
14769     return;
14770   }
14771
14772   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14773
14774   for(i=0;i<MAX_CIP_TYPES;i++)
14775   {
14776     info_mask_group[i] = 0;
14777     cip_mask_group [i] = 0;
14778   }
14779   for(i=0;i<MAX_APPL;i++)
14780   {
14781     appl_number_group_type[i] = 0;
14782   }
14783   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14784   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14785     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14786     {
14787       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14788       return; /* allow good application unfiltered access */
14789     }
14790   }
14791   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14792   {
14793     if(application[i].Id && a->CIP_Mask[i] )
14794     {
14795       for(k=0,busy=false; k<a->max_plci; k++)
14796       {
14797         if(a->plci[k].Id) 
14798         {
14799           auxplci = &a->plci[k];
14800           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14801           {
14802             busy = true;
14803             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14804           }
14805           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14806           {
14807             busy = true;
14808             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14809           }
14810         }
14811       }
14812
14813       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14814       {
14815         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14816         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14817           appl_number_group_type[i] = MAX_CIP_TYPES;
14818           group_found=true;
14819           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14820         }
14821         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14822         {                                      /* is group already present ?                  */
14823           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14824           group_found=true;
14825           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]));
14826         }
14827         else if(!info_mask_group[j])
14828         {                                      /* establish a new group                       */
14829           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14830           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14831           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14832           group_found=true;
14833           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]));
14834         }
14835       }
14836     }
14837   }
14838         
14839   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14840   {
14841     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14842     {
14843       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14844       {
14845         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14846       }
14847       else
14848       {
14849         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14850         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14851         {
14852           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14853           {
14854             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14855             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14856             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14857           }
14858         }
14859       }
14860     }
14861     else                                                 /* application should not get a call */
14862     {
14863       clear_group_ind_mask_bit (plci, i);
14864     }
14865   }
14866
14867 }
14868
14869
14870
14871 /* OS notifies the driver about a application Capi_Register */
14872 word CapiRegister(word id)
14873 {
14874   word i,j,appls_found;
14875
14876   PLCI   *plci;
14877   DIVA_CAPI_ADAPTER   *a;
14878
14879   for(i=0,appls_found=0; i<max_appl; i++)
14880   {
14881     if( application[i].Id && (application[i].Id!=id) )
14882     {
14883       appls_found++;                       /* an application has been found */
14884     }
14885   }
14886
14887   if(appls_found) return true;
14888   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14889   {
14890     a = &adapter[i];
14891     if(a->request)
14892     {
14893       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14894       {
14895         if(!appls_found)           /* first application does a capi register   */
14896         {
14897           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14898           {
14899             plci = &a->plci[j-1];
14900             plci->command = 0;
14901             add_p(plci,OAD,"\x01\xfd");
14902             add_p(plci,CAI,"\x01\x80");
14903             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14904             add_p(plci,SHIFT|6,NULL);
14905             add_p(plci,SIN,"\x02\x00\x00");
14906             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14907             sig_req(plci,ASSIGN,DSIG_ID);
14908             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14909             sig_req(plci,SIG_CTRL,0);
14910             send_req(plci);
14911           }
14912         }
14913       }
14914     }
14915   }
14916   return false;
14917 }
14918
14919 /*------------------------------------------------------------------*/
14920
14921 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14922
14923 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14924 {
14925  word i;
14926  /* Format of vswitch_t:
14927  0 byte length
14928  1 byte VSWITCHIE
14929  2 byte VSWITCH_REQ/VSWITCH_IND
14930  3 byte reserved
14931  4 word VSwitchcommand
14932  6 word returnerror
14933  8... Params
14934  */
14935  if(!plci ||
14936   !plci->appl ||
14937   !plci->State ||
14938   plci->Sig.Ind==NCR_FACILITY
14939   )
14940   return;
14941  
14942  for(i=0;i<MAX_MULTI_IE;i++)
14943  {
14944         if(!parms[i][0]) continue;
14945   if(parms[i][0]<7)
14946   {
14947    parms[i][0]=0; /* kill it */
14948    continue;
14949   }
14950   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14951   switch(parms[i][4])
14952   {
14953   case VSJOIN:
14954    if(!plci->relatedPTYPLCI ||
14955     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14956    { /* Error */
14957     break;
14958    }
14959    /* remember all necessary informations */
14960    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14961    {
14962     break;
14963    }
14964    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14965    {   /* first indication after ECT-Request on Consultation Call */
14966     plci->vswitchstate=parms[i][9];
14967     parms[i][9]=2; /* State */
14968     /* now ask first Call to join */
14969    }
14970    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14971    { /* Answer of VSWITCH_REQ from first Call */
14972     plci->vswitchstate=parms[i][9];
14973     /* tell consultation call to join
14974     and the protocol capabilities of the first call */
14975    }
14976    else
14977    { /* Error */
14978     break;
14979    }    
14980    plci->vsprot=parms[i][10]; /* protocol */
14981    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14982    /* send join request to related PLCI */
14983    parms[i][1]=VSWITCHIE;
14984    parms[i][2]=VSWITCH_REQ;
14985    
14986    plci->relatedPTYPLCI->command = 0;
14987    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14988    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14989    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14990    send_req(plci->relatedPTYPLCI);
14991    break;
14992   case VSTRANSPORT:
14993   default:
14994    if(plci->relatedPTYPLCI &&
14995     plci->vswitchstate==3 &&
14996     plci->relatedPTYPLCI->vswitchstate==3)
14997    {
14998     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14999     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15000     send_req(plci->relatedPTYPLCI);
15001    }
15002    break;
15003   }  
15004   parms[i][0]=0; /* kill it */
15005  }
15006 }
15007
15008
15009 /*------------------------------------------------------------------*/
15010
15011 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
15012   ENTITY e;
15013   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15014
15015   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15016     return (-1);
15017   }
15018
15019   pReq->xdi_dma_descriptor_operation.Req = 0;
15020   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15021
15022   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15023   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15024   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15025   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15026
15027   e.user[0] = plci->adapter->Id - 1;
15028   plci->adapter->request((ENTITY*)pReq);
15029
15030   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15031       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15032       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15033     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15034     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15035          plci->adapter->Id,
15036          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15037          *dma_magic));
15038     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15039   } else {
15040     dbug(1,dprintf("dma_alloc failed"));
15041     return (-1);
15042   }
15043 }
15044
15045 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15046   ENTITY e;
15047   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15048
15049   if (nr < 0) {
15050     return;
15051   }
15052
15053   pReq->xdi_dma_descriptor_operation.Req = 0;
15054   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15055
15056   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15057   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15058   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15059   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15060
15061   e.user[0] = plci->adapter->Id - 1;
15062   plci->adapter->request((ENTITY*)pReq);
15063
15064   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15065     dbug(1,dprintf("dma_free(%d)", nr));
15066   } else {
15067     dbug(1,dprintf("dma_free failed (%d)", nr));
15068   }
15069 }
15070
15071 /*------------------------------------------------------------------*/