]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/isdn/hardware/eicon/message.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/czankel/xtensa-2.6
[linux-2.6-omap-h63xx.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3   Copyright (c) Eicon Networks, 2002.
4  *
5   This source file is supplied for the use with
6   Eicon Networks range of DIVA Server Adapters.
7  *
8   Eicon File Revision :    2.1
9  *
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2, or (at your option)
13   any later version.
14  *
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18   See the GNU General Public License for more details.
19  *
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67  */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
75 static void set_group_ind_mask (PLCI   *plci);
76 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
77 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL   *, CAPI_MSG   *);
82 static word api_parse(byte   *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
84 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI   *);
90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
92
93 void   callback(ENTITY   *);
94
95 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI   *, byte);
97 static void data_ack(PLCI   *, byte);
98 static void sig_ind(PLCI   *);
99 static void SendInfo(PLCI   *, dword, byte   * *, byte);
100 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
101 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
102
103 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
104
105 static void nl_ind(PLCI   *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER   *);
133 static void add_p(PLCI   *, byte, byte   *);
134 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
137 static void add_d(PLCI   *, word, byte   *);
138 static void add_ai(PLCI   *, API_PARSE *);
139 static word add_b1(PLCI   *, API_PARSE *, word, word);
140 static word add_b23(PLCI   *, API_PARSE *);
141 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI   *, byte, byte);
143 static void nl_req_ncci(PLCI   *, byte, byte);
144 static void send_req(PLCI   *);
145 static void send_data(PLCI   *);
146 static word plci_remove_check(PLCI   *);
147 static void listen_check(DIVA_CAPI_ADAPTER   *);
148 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI   *, word *, byte   **, byte);
151 static byte ie_compare(byte   *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
153 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
154
155 /*
156   XON protocol helpers
157   */
158 static void channel_flow_control_remove (PLCI   * plci);
159 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI   * plci, byte ch);
161 static void channel_request_xon (PLCI   * plci, byte ch);
162 static void channel_xmit_xon (PLCI   * plci);
163 static int channel_can_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI   * plci);
165
166 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
169 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
170 static void VoiceChannelOff(PLCI   *plci);
171 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
172 static void adv_voice_clear_config (PLCI   *plci);
173
174 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
189 static void init_b1_config (PLCI   *plci);
190 static void clear_b1_config (PLCI   *plci);
191
192 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI   *plci);
195 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
196 static void dtmf_parameter_write (PLCI   *plci);
197
198
199 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
201 static void mixer_clear_config (PLCI   *plci);
202 static void mixer_notify_update (PLCI   *plci, byte others);
203 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_remove (PLCI   *plci);
209
210
211 static void ec_command (dword Id, PLCI   *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
214
215
216 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
218
219
220 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
221 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231
232 void   sendf(APPL   *, word, dword, word, byte *, ...);
233 void   * TransmitBufferSet(APPL   * appl, dword ref);
234 void   * TransmitBufferGet(APPL   * appl, void   * p);
235 void TransmitBufferFree(APPL   * appl, void   * p);
236 void   * ReceiveBufferGet(APPL   * appl, int Num);
237
238 int fax_head_line_time (char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER   * adapter;
247 extern APPL   * application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260   word command;
261   byte * format;
262   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
263 } ftable[] = {
264   {_DATA_B3_R,                          "dwww",         data_b3_req},
265   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
266   {_INFO_R,                             "ss",           info_req},
267   {_INFO_I|RESPONSE,                    "",             info_res},
268   {_CONNECT_R,                          "wsssssssss",   connect_req},
269   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
270   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
271   {_DISCONNECT_R,                       "s",            disconnect_req},
272   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
273   {_LISTEN_R,                           "dddss",        listen_req},
274   {_ALERT_R,                            "s",            alert_req},
275   {_FACILITY_R,                         "ws",           facility_req},
276   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
277   {_CONNECT_B3_R,                       "s",            connect_b3_req},
278   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
279   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
280   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
282   {_RESET_B3_R,                         "s",            reset_b3_req},
283   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
284   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
286   {_SELECT_B_REQ,                       "s",            select_b_req},
287   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
289   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
290 };
291
292 static byte * cip_bc[29][2] = {
293   { "",                     ""                     }, /* 0 */
294   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303   { "",                     ""                     }, /* 10 */
304   { "",                     ""                     }, /* 11 */
305   { "",                     ""                     }, /* 12 */
306   { "",                     ""                     }, /* 13 */
307   { "",                     ""                     }, /* 14 */
308   { "",                     ""                     }, /* 15 */
309
310   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte * cip_hlc[29] = {
326   "",                           /* 0 */
327   "",                           /* 1 */
328   "",                           /* 2 */
329   "",                           /* 3 */
330   "",                           /* 4 */
331   "",                           /* 5 */
332   "",                           /* 6 */
333   "",                           /* 7 */
334   "",                           /* 8 */
335   "",                           /* 9 */
336   "",                           /* 10 */
337   "",                           /* 11 */
338   "",                           /* 12 */
339   "",                           /* 13 */
340   "",                           /* 14 */
341   "",                           /* 15 */
342
343   "\x02\x91\x81",               /* 16 */
344   "\x02\x91\x84",               /* 17 */
345   "\x02\x91\xa1",               /* 18 */
346   "\x02\x91\xa4",               /* 19 */
347   "\x02\x91\xa8",               /* 20 */
348   "\x02\x91\xb1",               /* 21 */
349   "\x02\x91\xb2",               /* 22 */
350   "\x02\x91\xb5",               /* 23 */
351   "\x02\x91\xb8",               /* 24 */
352   "\x02\x91\xc1",               /* 25 */
353   "\x02\x91\x81",               /* 26 */
354   "\x03\x91\xe0\x01",           /* 27 */
355   "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL   * appl, CAPI_MSG   * msg)
387 {
388   word i, j, k, l, n;
389   word ret;
390   byte c;
391   byte controller;
392   DIVA_CAPI_ADAPTER   * a;
393   PLCI   * plci;
394   NCCI   * ncci_ptr;
395   word ncci;
396   CAPI_MSG   *m;
397     API_PARSE msg_parms[MAX_MSG_PARMS+1];
398
399   if (msg->header.length < sizeof (msg->header) ||
400       msg->header.length > MAX_MSG_SIZE) {
401     dbug(1,dprintf("bad len"));
402     return _BAD_MSG;
403   }
404
405   controller = (byte)((msg->header.controller &0x7f)-1);
406
407   /* controller starts with 0 up to (max_adapter - 1) */
408   if ( controller >= max_adapter )
409   {
410     dbug(1,dprintf("invalid ctrl"));
411     return _BAD_MSG;
412   }
413   
414   a = &adapter[controller];
415   plci = NULL;
416   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417   {
418     dbug(1,dprintf("plci=%x",msg->header.plci));
419     plci = &a->plci[msg->header.plci-1];
420     ncci = GET_WORD(&msg->header.ncci);
421     if (plci->Id
422      && (plci->appl
423       || (plci->State == INC_CON_PENDING)
424       || (plci->State == INC_CON_ALERT)
425       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426      && ((ncci == 0)
427       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429     {
430       i = plci->msg_in_read_pos;
431       j = plci->msg_in_write_pos;
432       if (j >= i)
433       {
434         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435           i += MSG_IN_QUEUE_SIZE - j;
436         else
437           j = 0;
438       }
439       else
440       {
441
442         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444         if (i > MSG_IN_QUEUE_SIZE - n)
445           i = MSG_IN_QUEUE_SIZE - n + 1;
446         i -= j;
447       }
448
449       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451       {
452         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453           msg->header.length, plci->msg_in_write_pos,
454           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456         return _QUEUE_FULL;
457       }
458       c = false;
459       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
460        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461       {
462         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463           c = true;
464       }
465       if (msg->header.command == _DATA_B3_R)
466       {
467         if (msg->header.length < 20)
468         {
469           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470           return _BAD_MSG;
471         }
472         ncci_ptr = &(a->ncci[ncci]);
473         n = ncci_ptr->data_pending;
474         l = ncci_ptr->data_ack_pending;
475         k = plci->msg_in_read_pos;
476         while (k != plci->msg_in_write_pos)
477         {
478           if (k == plci->msg_in_wrap_pos)
479             k = 0;
480           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482           {
483             n++;
484             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485               l++;
486           }
487
488           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
489             MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491         }
492         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493         {
494           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497           return _QUEUE_FULL;
498         }
499         if (plci->req_in || plci->internal_command)
500         {
501           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
502            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503           {
504             dbug(0,dprintf("Q-FULL3(requeue)"));
505
506             return _QUEUE_FULL;
507           }
508           c = true;
509         }
510       }
511       else
512       {
513         if (plci->req_in || plci->internal_command)
514           c = true;
515         else
516         {
517           plci->command = msg->header.command;
518           plci->number = msg->header.number;
519         }
520       }
521       if (c)
522       {
523         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524           msg->header.command, plci->req_in, plci->internal_command,
525           msg->header.length, plci->msg_in_write_pos,
526           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527         if (j == 0)
528           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
530         for (i = 0; i < msg->header.length; i++)
531           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
532         if (m->header.command == _DATA_B3_R)
533         {
534
535           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
536
537         }
538
539         j = (j + 3) & 0xfffc;
540
541         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
542         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543         return 0;
544       }
545     }
546     else
547     {
548       plci = NULL;
549     }
550   }
551   dbug(1,dprintf("com=%x",msg->header.command));
552
553   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554   for(i=0, ret = _BAD_MSG;
555       i<(sizeof(ftable)/sizeof(struct _ftable));
556       i++) {
557
558     if(ftable[i].command==msg->header.command) {
559       /* break loop if the message is correct, otherwise continue scan  */
560       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
561       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
562         ret = 0;
563         break;
564       }
565       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
566     }
567   }
568   if(ret) {
569     dbug(1,dprintf("BAD_MSG"));
570     if(plci) plci->command = 0;
571     return ret;
572   }
573
574
575   c = ftable[i].function(GET_DWORD(&msg->header.controller),
576                          msg->header.number,
577                          a,
578                          plci,
579                          appl,
580                          msg_parms);
581
582   channel_xmit_extended_xon (plci);
583
584   if(c==1) send_req(plci);
585   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
586   if(plci && !plci->req_in) plci->command = 0;
587   return 0;
588 }
589
590
591 /*------------------------------------------------------------------*/
592 /* api_parse function, check the format of api messages             */
593 /*------------------------------------------------------------------*/
594
595 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
596 {
597   word i;
598   word p;
599
600   for(i=0,p=0; format[i]; i++) {
601     if(parms)
602     {
603       parms[i].info = &msg[p];
604     }
605     switch(format[i]) {
606     case 'b':
607       p +=1;
608       break;
609     case 'w':
610       p +=2;
611       break;
612     case 'd':
613       p +=4;
614       break;
615     case 's':
616       if(msg[p]==0xff) {
617         parms[i].info +=2;
618         parms[i].length = msg[p+1] + (msg[p+2]<<8);
619         p +=(parms[i].length +3);
620       }
621       else {
622         parms[i].length = msg[p];
623         p +=(parms[i].length +1);
624       }
625       break;
626     }
627
628     if(p>length) return true;
629   }
630   if(parms) parms[i].info = NULL;
631   return false;
632 }
633
634 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
635 {
636   word i, j, n = 0;
637   byte   *p;
638
639   p = out->info;
640   for (i = 0; format[i] != '\0'; i++)
641   {
642     out->parms[i].info = p;
643     out->parms[i].length = in[i].length;
644     switch (format[i])
645     {
646     case 'b':
647       n = 1;
648       break;
649     case 'w':
650       n = 2;
651       break;
652     case 'd':
653       n = 4;
654       break;
655     case 's':
656       n = in[i].length + 1;
657       break;
658     }
659     for (j = 0; j < n; j++)
660       *(p++) = in[i].info[j];
661   }
662   out->parms[i].info = NULL;
663   out->parms[i].length = 0;
664 }
665
666 static void api_load_msg(API_SAVE *in, API_PARSE *out)
667 {
668   word i;
669
670   i = 0;
671   do
672   {
673     out[i].info = in->parms[i].info;
674     out[i].length = in->parms[i].length;
675   } while (in->parms[i++].info);
676 }
677
678
679 /*------------------------------------------------------------------*/
680 /* CAPI remove function                                             */
681 /*------------------------------------------------------------------*/
682
683 word api_remove_start(void)
684 {
685   word i;
686   word j;
687
688   if(!remove_started) {
689     remove_started = true;
690     for(i=0;i<max_adapter;i++) {
691       if(adapter[i].request) {
692         for(j=0;j<adapter[i].max_plci;j++) {
693           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
694         }
695       }
696     }
697     return 1;
698   }
699   else {
700     for(i=0;i<max_adapter;i++) {
701       if(adapter[i].request) {
702         for(j=0;j<adapter[i].max_plci;j++) {
703           if(adapter[i].plci[j].Sig.Id) return 1;
704         }
705       }
706     }
707   }
708   api_remove_complete();
709   return 0;
710 }
711
712
713 /*------------------------------------------------------------------*/
714 /* internal command queue                                           */
715 /*------------------------------------------------------------------*/
716
717 static void init_internal_command_queue (PLCI   *plci)
718 {
719   word i;
720
721   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
722     (char   *)(FILE_), __LINE__));
723
724   plci->internal_command = 0;
725   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
726     plci->internal_command_queue[i] = NULL;
727 }
728
729
730 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
731 {
732   word i;
733
734   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
735     UnMapId (Id), (char   *)(FILE_), __LINE__));
736
737   if (plci->internal_command == 0)
738   {
739     plci->internal_command_queue[0] = command_function;
740     (* command_function)(Id, plci, OK);
741   }
742   else
743   {
744     i = 1;
745     while (plci->internal_command_queue[i] != NULL)
746       i++;
747     plci->internal_command_queue[i] = command_function;
748   }
749 }
750
751
752 static void next_internal_command (dword Id, PLCI   *plci)
753 {
754   word i;
755
756   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
757     UnMapId (Id), (char   *)(FILE_), __LINE__));
758
759   plci->internal_command = 0;
760   plci->internal_command_queue[0] = NULL;
761   while (plci->internal_command_queue[1] != NULL)
762   {
763     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
764       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
765     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
766     (*(plci->internal_command_queue[0]))(Id, plci, OK);
767     if (plci->internal_command != 0)
768       return;
769     plci->internal_command_queue[0] = NULL;
770   }
771 }
772
773
774 /*------------------------------------------------------------------*/
775 /* NCCI allocate/remove function                                    */
776 /*------------------------------------------------------------------*/
777
778 static dword ncci_mapping_bug = 0;
779
780 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
781 {
782   DIVA_CAPI_ADAPTER   *a;
783   word ncci, i, j, k;
784
785   a = plci->adapter;
786   if (!ch || a->ch_ncci[ch])
787   {
788     ncci_mapping_bug++;
789     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
790       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
791     ncci = ch;
792   }
793   else
794   {
795     if (force_ncci)
796       ncci = force_ncci;
797     else
798     {
799       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
800         ncci = ch;
801       else
802       {
803         ncci = 1;
804         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
805           ncci++;
806         if (ncci == MAX_NCCI+1)
807         {
808           ncci_mapping_bug++;
809           i = 1;
810           do
811           {
812             j = 1;
813             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
814               j++;
815             k = j;
816             if (j < MAX_NCCI+1)
817             {
818               do
819               {
820                 j++;
821               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
822             }
823           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
824           if (i < MAX_NL_CHANNEL+1)
825           {
826             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
827               ncci_mapping_bug, ch, force_ncci, i, k, j));
828           }
829           else
830           {
831             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
832               ncci_mapping_bug, ch, force_ncci));
833           }
834           ncci = ch;
835         }
836       }
837       a->ncci_plci[ncci] = plci->Id;
838       a->ncci_state[ncci] = IDLE;
839       if (!plci->ncci_ring_list)
840         plci->ncci_ring_list = ncci;
841       else
842         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
843       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
844     }
845     a->ncci_ch[ncci] = ch;
846     a->ch_ncci[ch] = (byte) ncci;
847     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
848       ncci_mapping_bug, ch, force_ncci, ch, ncci));
849   }
850   return (ncci);
851 }
852
853
854 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
855 {
856   DIVA_CAPI_ADAPTER   *a;
857   APPL   *appl;
858   word i, ncci_code;
859   dword Id;
860
861   a = plci->adapter;
862   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
863   if (ncci)
864   {
865     if (a->ncci_plci[ncci] == plci->Id)
866     {
867       if (!plci->appl)
868       {
869         ncci_mapping_bug++;
870         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
871           ncci_mapping_bug, Id));
872       }
873       else
874       {
875         appl = plci->appl;
876         ncci_code = ncci | (((word) a->Id) << 8);
877         for (i = 0; i < appl->MaxBuffer; i++)
878         {
879           if ((appl->DataNCCI[i] == ncci_code)
880            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
881           {
882             appl->DataNCCI[i] = 0;
883           }
884         }
885       }
886     }
887   }
888   else
889   {
890     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
891     {
892       if (a->ncci_plci[ncci] == plci->Id)
893       {
894         if (!plci->appl)
895         {
896           ncci_mapping_bug++;
897           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
898             ncci_mapping_bug, Id));
899         }
900         else
901         {
902           appl = plci->appl;
903           ncci_code = ncci | (((word) a->Id) << 8);
904           for (i = 0; i < appl->MaxBuffer; i++)
905           {
906             if ((appl->DataNCCI[i] == ncci_code)
907              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
908             {
909               appl->DataNCCI[i] = 0;
910             }
911           }
912         }
913       }
914     }
915   }
916 }
917
918
919 static void cleanup_ncci_data (PLCI   *plci, word ncci)
920 {
921   NCCI   *ncci_ptr;
922
923   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
924   {
925     ncci_ptr = &(plci->adapter->ncci[ncci]);
926     if (plci->appl)
927     {
928       while (ncci_ptr->data_pending != 0)
929       {
930         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
931           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
932         (ncci_ptr->data_out)++;
933         if (ncci_ptr->data_out == MAX_DATA_B3)
934           ncci_ptr->data_out = 0;
935         (ncci_ptr->data_pending)--;
936       }
937     }
938     ncci_ptr->data_out = 0;
939     ncci_ptr->data_pending = 0;
940     ncci_ptr->data_ack_out = 0;
941     ncci_ptr->data_ack_pending = 0;
942   }
943 }
944
945
946 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
947 {
948   DIVA_CAPI_ADAPTER   *a;
949   dword Id;
950   word i;
951
952   a = plci->adapter;
953   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
954   if (!preserve_ncci)
955     ncci_free_receive_buffers (plci, ncci);
956   if (ncci)
957   {
958     if (a->ncci_plci[ncci] != plci->Id)
959     {
960       ncci_mapping_bug++;
961       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
962         ncci_mapping_bug, Id, preserve_ncci));
963     }
964     else
965     {
966       cleanup_ncci_data (plci, ncci);
967       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
968         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
969       a->ch_ncci[a->ncci_ch[ncci]] = 0;
970       if (!preserve_ncci)
971       {
972         a->ncci_ch[ncci] = 0;
973         a->ncci_plci[ncci] = 0;
974         a->ncci_state[ncci] = IDLE;
975         i = plci->ncci_ring_list;
976         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
977           i = a->ncci_next[i];
978         if ((i != 0) && (a->ncci_next[i] == ncci))
979         {
980           if (i == ncci)
981             plci->ncci_ring_list = 0;
982           else if (plci->ncci_ring_list == ncci)
983             plci->ncci_ring_list = i;
984           a->ncci_next[i] = a->ncci_next[ncci];
985         }
986         a->ncci_next[ncci] = 0;
987       }
988     }
989   }
990   else
991   {
992     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
993     {
994       if (a->ncci_plci[ncci] == plci->Id)
995       {
996         cleanup_ncci_data (plci, ncci);
997         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
998           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
999         a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000         if (!preserve_ncci)
1001         {
1002           a->ncci_ch[ncci] = 0;
1003           a->ncci_plci[ncci] = 0;
1004           a->ncci_state[ncci] = IDLE;
1005           a->ncci_next[ncci] = 0;
1006         }
1007       }
1008     }
1009     if (!preserve_ncci)
1010       plci->ncci_ring_list = 0;
1011   }
1012 }
1013
1014
1015 /*------------------------------------------------------------------*/
1016 /* PLCI remove function                                             */
1017 /*------------------------------------------------------------------*/
1018
1019 static void plci_free_msg_in_queue (PLCI   *plci)
1020 {
1021   word i;
1022
1023   if (plci->appl)
1024   {
1025     i = plci->msg_in_read_pos;
1026     while (i != plci->msg_in_write_pos)
1027     {
1028       if (i == plci->msg_in_wrap_pos)
1029         i = 0;
1030       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031       {
1032
1033         TransmitBufferFree (plci->appl,
1034           (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1035
1036       }
1037
1038       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1039         MSG_IN_OVERHEAD + 3) & 0xfffc;
1040
1041     }
1042   }
1043   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1046 }
1047
1048
1049 static void plci_remove(PLCI   * plci)
1050 {
1051
1052   if(!plci) {
1053     dbug(1,dprintf("plci_remove(no plci)"));
1054     return;
1055   }
1056   init_internal_command_queue (plci);
1057   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058   if(plci_remove_check(plci))
1059   {
1060     return;
1061   }
1062   if (plci->Sig.Id == 0xff)
1063   {
1064     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065     if (plci->NL.Id && !plci->nl_remove_id)
1066     {
1067       nl_req_ncci(plci,REMOVE,0);
1068       send_req(plci);
1069     }
1070   }
1071   else
1072   {
1073     if (!plci->sig_remove_id
1074      && (plci->Sig.Id
1075       || (plci->req_in!=plci->req_out)
1076       || (plci->nl_req || plci->sig_req)))
1077     {
1078       sig_req(plci,HANGUP,0);
1079       send_req(plci);
1080     }
1081   }
1082   ncci_remove (plci, 0, false);
1083   plci_free_msg_in_queue (plci);
1084
1085   plci->channels = 0;
1086   plci->appl = NULL;
1087   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088     plci->State = OUTG_DIS_PENDING;
1089 }
1090
1091 /*------------------------------------------------------------------*/
1092 /* Application Group function helpers                               */
1093 /*------------------------------------------------------------------*/
1094
1095 static void set_group_ind_mask (PLCI   *plci)
1096 {
1097   word i;
1098
1099   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100     plci->group_optimization_mask_table[i] = 0xffffffffL;
1101 }
1102
1103 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1104 {
1105   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106 }
1107
1108 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1109 {
1110   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111 }
1112
1113 /*------------------------------------------------------------------*/
1114 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1115 /*------------------------------------------------------------------*/
1116
1117 static void clear_c_ind_mask (PLCI   *plci)
1118 {
1119   word i;
1120
1121   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122     plci->c_ind_mask_table[i] = 0;
1123 }
1124
1125 static byte c_ind_mask_empty (PLCI   *plci)
1126 {
1127   word i;
1128
1129   i = 0;
1130   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1131     i++;
1132   return (i == C_IND_MASK_DWORDS);
1133 }
1134
1135 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1136 {
1137   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138 }
1139
1140 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1141 {
1142   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143 }
1144
1145 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1146 {
1147   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148 }
1149
1150 static void dump_c_ind_mask (PLCI   *plci)
1151 {
1152 static char hex_digit_table[0x10] =
1153   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1154   word i, j, k;
1155   dword d;
1156     char *p;
1157     char buf[40];
1158
1159   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1160   {
1161     p = buf + 36;
1162     *p = '\0';
1163     for (j = 0; j < 4; j++)
1164     {
1165       if (i+j < C_IND_MASK_DWORDS)
1166       {
1167         d = plci->c_ind_mask_table[i+j];
1168         for (k = 0; k < 8; k++)
1169         {
1170           *(--p) = hex_digit_table[d & 0xf];
1171           d >>= 4;
1172         }
1173       }
1174       else if (i != 0)
1175       {
1176         for (k = 0; k < 8; k++)
1177           *(--p) = ' ';
1178       }
1179       *(--p) = ' ';
1180     }
1181     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1182   }
1183 }
1184
1185
1186
1187
1188
1189 #define dump_plcis(a)
1190
1191
1192
1193 /*------------------------------------------------------------------*/
1194 /* translation function for each message                            */
1195 /*------------------------------------------------------------------*/
1196
1197 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1198 {
1199   word ch;
1200   word i;
1201   word Info;
1202   word CIP;
1203   byte LinkLayer;
1204   API_PARSE * ai;
1205   API_PARSE * bp;
1206     API_PARSE ai_parms[5];
1207   word channel = 0;
1208   dword ch_mask;
1209   byte m;
1210   static byte esc_chi[35] = {0x02,0x18,0x01};
1211   static byte lli[2] = {0x01,0x00};
1212   byte noCh = 0;
1213   word dir = 0;
1214   byte   *p_chi = "";
1215
1216   for(i=0;i<5;i++) ai_parms[i].length = 0;
1217
1218   dbug(1,dprintf("connect_req(%d)",parms->length));
1219   Info = _WRONG_IDENTIFIER;
1220   if(a)
1221   {
1222     if(a->adapter_disabled)
1223     {
1224       dbug(1,dprintf("adapter disabled"));
1225       Id = ((word)1<<8)|a->Id;
1226       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1227       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1228       return false;
1229     }
1230     Info = _OUT_OF_PLCI;
1231     if((i=get_plci(a)))
1232     {
1233       Info = 0;
1234       plci = &a->plci[i-1];
1235       plci->appl = appl;
1236       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1237       /* check 'external controller' bit for codec support */
1238       if(Id & EXT_CONTROLLER)
1239       {
1240         if(AdvCodecSupport(a, plci, appl, 0) )
1241         {
1242           plci->Id = 0;
1243           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1244           return 2;
1245         }
1246       }
1247       ai = &parms[9];
1248       bp = &parms[5];
1249       ch = 0;
1250       if(bp->length)LinkLayer = bp->info[3];
1251       else LinkLayer = 0;
1252       if(ai->length)
1253       {
1254         ch=0xffff;
1255         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1256         {
1257           ch = 0;
1258           if(ai_parms[0].length)
1259           {
1260             ch = GET_WORD(ai_parms[0].info+1);
1261             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1262             if(ch==4) /* explizit CHI in message */
1263             {
1264               /* check length of B-CH struct */
1265               if((ai_parms[0].info)[3]>=1)
1266               {
1267                 if((ai_parms[0].info)[4]==CHI)
1268                 {
1269                   p_chi = &((ai_parms[0].info)[5]);
1270                 }
1271                 else
1272                 {
1273                   p_chi = &((ai_parms[0].info)[3]);
1274                 }
1275                 if(p_chi[0]>35) /* check length of channel ID */
1276                 {
1277                   Info = _WRONG_MESSAGE_FORMAT;    
1278                 }
1279               }
1280               else Info = _WRONG_MESSAGE_FORMAT;    
1281             }
1282
1283             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1284             {
1285               dir = GET_WORD(ai_parms[0].info+3);
1286               ch_mask = 0;
1287               m = 0x3f;
1288               for(i=0; i+5<=ai_parms[0].length; i++)
1289               {
1290                 if(ai_parms[0].info[i+5]!=0)
1291                 {
1292                   if((ai_parms[0].info[i+5] | m) != 0xff)
1293                     Info = _WRONG_MESSAGE_FORMAT;
1294                   else
1295                   {
1296                     if (ch_mask == 0)
1297                       channel = i;
1298                     ch_mask |= 1L << i;
1299                   }
1300                 }
1301                 m = 0;
1302               }
1303               if (ch_mask == 0)
1304                 Info = _WRONG_MESSAGE_FORMAT;
1305               if (!Info)
1306               {
1307                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1308                 {
1309                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1310                   for(i=0; i+5<=ai_parms[0].length; i++)
1311                     esc_chi[i+3] = ai_parms[0].info[i+5];
1312                 }
1313                 else
1314                   esc_chi[0] = 2;
1315                 esc_chi[2] = (byte)channel;
1316                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1317                 add_p(plci,LLI,lli);
1318                 add_p(plci,ESC,esc_chi);
1319                 plci->State = LOCAL_CONNECT;
1320                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1321               }
1322             }
1323           }
1324         }
1325         else  Info = _WRONG_MESSAGE_FORMAT;
1326       }
1327
1328       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1329       plci->command = _CONNECT_R;
1330       plci->number = Number;
1331       /* x.31 or D-ch free SAPI in LinkLayer? */
1332       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1333       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1334       {
1335         /* B-channel used for B3 connections (ch==0), or no B channel    */
1336         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1337         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1338         else     Info = add_b1(plci,&parms[5],ch,0); 
1339         add_s(plci,OAD,&parms[2]);
1340         add_s(plci,OSA,&parms[4]);
1341         add_s(plci,BC,&parms[6]);
1342         add_s(plci,LLC,&parms[7]);
1343         add_s(plci,HLC,&parms[8]);
1344         CIP = GET_WORD(parms[0].info);
1345         if (a->Info_Mask[appl->Id-1] & 0x200)
1346         {
1347           /* early B3 connect (CIP mask bit 9) no release after a disc */
1348           add_p(plci,LLI,"\x01\x01");
1349         }
1350         if(GET_WORD(parms[0].info)<29) {
1351           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1352           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1353         }
1354         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1355         sig_req(plci,ASSIGN,DSIG_ID);
1356       }
1357       else if(ch==1) {
1358
1359         /* D-Channel used for B3 connections */
1360         plci->Sig.Id = 0xff;
1361         Info = 0;
1362       }
1363
1364       if(!Info && ch!=2 && !noCh ) {
1365         Info = add_b23(plci,&parms[5]);
1366         if(!Info) {
1367           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1368         }
1369       }
1370
1371       if(!Info)
1372       {
1373         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1374         {
1375           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1376           {
1377             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1378             plci->spoofed_msg = CALL_REQ;
1379             plci->internal_command = BLOCK_PLCI;
1380             plci->command = 0;
1381             dbug(1,dprintf("Spoof"));
1382             send_req(plci);
1383             return false;
1384           }
1385           if(ch==4)add_p(plci,CHI,p_chi);
1386           add_s(plci,CPN,&parms[1]);
1387           add_s(plci,DSA,&parms[3]);
1388           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1389           add_ai(plci,&parms[9]);
1390           if(!dir)sig_req(plci,CALL_REQ,0);
1391           else
1392           {
1393             plci->command = PERM_LIST_REQ;
1394             plci->appl = appl;
1395             sig_req(plci,LISTEN_REQ,0);
1396             send_req(plci);
1397             return false;
1398           }
1399         }
1400         send_req(plci);
1401         return false;
1402       }
1403       plci->Id = 0;
1404     }
1405   }
1406   sendf(appl,
1407         _CONNECT_R|CONFIRM,
1408         Id,
1409         Number,
1410         "w",Info);
1411   return 2;
1412 }
1413
1414 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1415 {
1416   word i, Info;
1417   word Reject;
1418   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1420   API_PARSE * ai;
1421     API_PARSE ai_parms[5];
1422   word ch=0;
1423
1424   if(!plci) {
1425     dbug(1,dprintf("connect_res(no plci)"));
1426     return 0;  /* no plci, no send */
1427   }
1428
1429   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430   for(i=0;i<5;i++) ai_parms[i].length = 0;
1431   ai = &parms[5];
1432   dbug(1,dprintf("ai->length=%d",ai->length));
1433
1434   if(ai->length)
1435   {
1436     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1437     {
1438       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1439       ch = 0;
1440       if(ai_parms[0].length)
1441       {
1442         ch = GET_WORD(ai_parms[0].info+1);
1443         dbug(1,dprintf("BCH-I=0x%x",ch));
1444       }
1445     }
1446   }
1447
1448   if(plci->State==INC_CON_CONNECTED_ALERT)
1449   {
1450     dbug(1,dprintf("Connected Alert Call_Res"));
1451     if (a->Info_Mask[appl->Id-1] & 0x200)
1452     {
1453     /* early B3 connect (CIP mask bit 9) no release after a disc */
1454       add_p(plci,LLI,"\x01\x01");
1455     }
1456     add_s(plci, CONN_NR, &parms[2]);
1457     add_s(plci, LLC, &parms[4]);
1458     add_ai(plci, &parms[5]);
1459     plci->State = INC_CON_ACCEPT;
1460     sig_req(plci, CALL_RES,0);
1461     return 1;
1462   }
1463   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465     dump_c_ind_mask (plci);
1466     Reject = GET_WORD(parms[0].info);
1467     dbug(1,dprintf("Reject=0x%x",Reject));
1468     if(Reject) 
1469     {
1470       if(c_ind_mask_empty (plci)) 
1471       {
1472         if((Reject&0xff00)==0x3400) 
1473         {
1474           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475           add_p(plci,ESC,esc_t);
1476           add_ai(plci, &parms[5]);
1477           sig_req(plci,REJECT,0);
1478         }      
1479         else if(Reject==1 || Reject>9) 
1480         {
1481           add_ai(plci, &parms[5]);
1482           sig_req(plci,HANGUP,0);
1483         }
1484         else 
1485         {
1486           esc_t[2] = cau_t[(Reject&0x000f)];
1487           add_p(plci,ESC,esc_t);
1488           add_ai(plci, &parms[5]);
1489           sig_req(plci,REJECT,0);
1490         }
1491         plci->appl = appl;
1492       }
1493       else 
1494       {
1495         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1496       }
1497     }
1498     else {
1499       plci->appl = appl;
1500       if(Id & EXT_CONTROLLER){
1501         if(AdvCodecSupport(a, plci, appl, 0)){
1502           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503           sig_req(plci,HANGUP,0);
1504           return 1;
1505         }
1506         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1507         {
1508           Info = add_b23(plci, &parms[1]);
1509           if (Info)
1510           {
1511             dbug(1,dprintf("connect_res(error from add_b23)"));
1512             sig_req(plci,HANGUP,0);
1513             return 1;
1514           }
1515           if(plci->adv_nl)
1516           {
1517             nl_req_ncci(plci, ASSIGN, 0);
1518           }
1519         }
1520       }
1521       else
1522       {
1523         plci->tel = 0;
1524         if(ch!=2)
1525         {
1526           Info = add_b23(plci, &parms[1]);
1527           if (Info)
1528           {
1529             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530             sig_req(plci,HANGUP,0);
1531             return 1;
1532           }
1533         }
1534         nl_req_ncci(plci, ASSIGN, 0);
1535       }
1536
1537       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1538       {
1539         api_save_msg(parms, "wsssss", &plci->saved_msg);
1540         plci->spoofed_msg = CALL_RES;
1541         plci->internal_command = BLOCK_PLCI;
1542         plci->command = 0;
1543         dbug(1,dprintf("Spoof"));
1544       }
1545       else
1546       {
1547         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548         if (a->Info_Mask[appl->Id-1] & 0x200)
1549         {
1550           /* early B3 connect (CIP mask bit 9) no release after a disc */
1551           add_p(plci,LLI,"\x01\x01");
1552         }
1553         add_s(plci, CONN_NR, &parms[2]);
1554         add_s(plci, LLC, &parms[4]);
1555         add_ai(plci, &parms[5]);
1556         plci->State = INC_CON_ACCEPT;
1557         sig_req(plci, CALL_RES,0);
1558       }
1559
1560       for(i=0; i<max_appl; i++) {
1561         if(test_c_ind_mask_bit (plci, i)) {
1562           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1563         }
1564       }
1565     }
1566   }
1567   return 1;
1568 }
1569
1570 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1571 {
1572   dbug(1,dprintf("connect_a_res"));
1573   return false;
1574 }
1575
1576 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1577 {
1578   word Info;
1579   word i;
1580
1581   dbug(1,dprintf("disconnect_req"));
1582
1583   Info = _WRONG_IDENTIFIER;
1584
1585   if(plci)
1586   {
1587     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1588     {
1589       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1590       plci->appl = appl;
1591       for(i=0; i<max_appl; i++)
1592       {
1593         if(test_c_ind_mask_bit (plci, i))
1594           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595       }
1596       plci->State = OUTG_DIS_PENDING;
1597     }
1598     if(plci->Sig.Id && plci->appl)
1599     {
1600       Info = 0;
1601         if(plci->Sig.Id!=0xff)
1602         {
1603           if(plci->State!=INC_DIS_PENDING)
1604           {
1605             add_ai(plci, &msg[0]);
1606             sig_req(plci,HANGUP,0);
1607             plci->State = OUTG_DIS_PENDING;
1608             return 1;
1609           }
1610         }
1611         else
1612         {
1613           if (plci->NL.Id && !plci->nl_remove_id)
1614           {
1615             mixer_remove (plci);
1616             nl_req_ncci(plci,REMOVE,0);
1617           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1618           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619           plci->State = INC_DIS_PENDING;
1620           }
1621           return 1;
1622         }
1623       }
1624     }
1625
1626   if(!appl)  return false;
1627   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1628   return false;
1629 }
1630
1631 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1632 {
1633   dbug(1,dprintf("disconnect_res"));
1634   if(plci)
1635   {
1636         /* clear ind mask bit, just in case of collsion of          */
1637         /* DISCONNECT_IND and CONNECT_RES                           */
1638     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1639     ncci_free_receive_buffers (plci, 0);
1640     if(plci_remove_check(plci))
1641     {
1642       return 0;
1643     }
1644     if(plci->State==INC_DIS_PENDING
1645     || plci->State==SUSPENDING) {
1646       if(c_ind_mask_empty (plci)) {
1647         if(plci->State!=SUSPENDING)plci->State = IDLE;
1648         dbug(1,dprintf("chs=%d",plci->channels));
1649         if(!plci->channels) {
1650           plci_remove(plci);
1651         }
1652       }
1653     }
1654   }
1655   return 0;
1656 }
1657
1658 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1659 {
1660   word Info;
1661   byte i;
1662
1663   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1664
1665   Info = _WRONG_IDENTIFIER;
1666   if(a) {
1667     Info = 0;
1668     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1669     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1670     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1671     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1672       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1673     }
1674
1675     /* check if external controller listen and switch listen on or off*/
1676     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1677       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1678         dummy_plci.State = IDLE;
1679         a->codec_listen[appl->Id-1] = &dummy_plci;
1680         a->TelOAD[0] = (byte)(parms[3].length);
1681         for(i=1;parms[3].length>=i && i<22;i++) {
1682           a->TelOAD[i] = parms[3].info[i];
1683         }
1684         a->TelOAD[i] = 0;
1685         a->TelOSA[0] = (byte)(parms[4].length);
1686         for(i=1;parms[4].length>=i && i<22;i++) {
1687           a->TelOSA[i] = parms[4].info[i];
1688         }
1689         a->TelOSA[i] = 0;
1690       }
1691       else Info = 0x2002; /* wrong controller, codec not supported */
1692     }
1693     else{               /* clear listen */
1694       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1695     }
1696   }
1697   sendf(appl,
1698         _LISTEN_R|CONFIRM,
1699         Id,
1700         Number,
1701         "w",Info);
1702
1703   if (a) listen_check(a);
1704   return false;
1705 }
1706
1707 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1708 {
1709   word i;
1710   API_PARSE * ai;
1711   PLCI   * rc_plci = NULL;
1712     API_PARSE ai_parms[5];
1713   word Info = 0;
1714
1715   dbug(1,dprintf("info_req"));
1716   for(i=0;i<5;i++) ai_parms[i].length = 0;
1717
1718   ai = &msg[1];
1719
1720   if(ai->length)
1721   {
1722     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1723     {
1724       dbug(1,dprintf("AddInfo wrong"));
1725       Info = _WRONG_MESSAGE_FORMAT;
1726     }
1727   }
1728   if(!a) Info = _WRONG_STATE;
1729
1730   if(!Info && plci)
1731   {                /* no fac, with CPN, or KEY */
1732     rc_plci = plci;
1733     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1734     {
1735       /* overlap sending option */
1736       dbug(1,dprintf("OvlSnd"));
1737       add_s(plci,CPN,&msg[0]);
1738       add_s(plci,KEY,&ai_parms[1]);
1739       sig_req(plci,INFO_REQ,0);
1740       send_req(plci);
1741       return false;
1742     }
1743
1744     if(plci->State && ai_parms[2].length)
1745     {
1746       /* User_Info option */
1747       dbug(1,dprintf("UUI"));
1748       add_s(plci,UUI,&ai_parms[2]);
1749       sig_req(plci,USER_DATA,0);
1750     }
1751     else if(plci->State && ai_parms[3].length)
1752     {
1753       /* Facility option */
1754       dbug(1,dprintf("FAC"));
1755       add_s(plci,CPN,&msg[0]);
1756       add_ai(plci, &msg[1]);
1757       sig_req(plci,FACILITY_REQ,0);
1758     }
1759     else
1760     {
1761       Info = _WRONG_STATE;
1762     }
1763   }
1764   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1765   {
1766     /* NCR_Facility option -> send UUI and Keypad too */
1767     dbug(1,dprintf("NCR_FAC"));
1768     if((i=get_plci(a)))
1769     {
1770       rc_plci = &a->plci[i-1];
1771       appl->NullCREnable  = true;
1772       rc_plci->internal_command = C_NCR_FAC_REQ;
1773       rc_plci->appl = appl;
1774       add_p(rc_plci,CAI,"\x01\x80");
1775       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1776       sig_req(rc_plci,ASSIGN,DSIG_ID);
1777       send_req(rc_plci);
1778     }
1779     else
1780     {
1781       Info = _OUT_OF_PLCI;
1782     }
1783
1784     if(!Info)
1785     {
1786       add_s(rc_plci,CPN,&msg[0]);
1787       add_ai(rc_plci, &msg[1]);
1788       sig_req(rc_plci,NCR_FACILITY,0);
1789       send_req(rc_plci);
1790       return false;
1791      /* for application controlled supplementary services    */
1792     }
1793   }
1794
1795   if (!rc_plci)
1796   {
1797     Info = _WRONG_MESSAGE_FORMAT;
1798   }
1799
1800   if(!Info)
1801   {
1802     send_req(rc_plci);
1803   }
1804   else
1805   {  /* appl is not assigned to a PLCI or error condition */
1806     dbug(1,dprintf("localInfoCon"));
1807     sendf(appl,
1808           _INFO_R|CONFIRM,
1809           Id,
1810           Number,
1811           "w",Info);
1812   }
1813   return false;
1814 }
1815
1816 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1817 {
1818   dbug(1,dprintf("info_res"));
1819   return false;
1820 }
1821
1822 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1823 {
1824   word Info;
1825   byte ret;
1826
1827   dbug(1,dprintf("alert_req"));
1828
1829   Info = _WRONG_IDENTIFIER;
1830   ret = false;
1831   if(plci) {
1832     Info = _ALERT_IGNORED;
1833     if(plci->State!=INC_CON_ALERT) {
1834       Info = _WRONG_STATE;
1835       if(plci->State==INC_CON_PENDING) {
1836         Info = 0;
1837         plci->State=INC_CON_ALERT;
1838         add_ai(plci, &msg[0]);
1839         sig_req(plci,CALL_ALERT,0);
1840         ret = 1;
1841       }
1842     }
1843   }
1844   sendf(appl,
1845         _ALERT_R|CONFIRM,
1846         Id,
1847         Number,
1848         "w",Info);
1849   return ret;
1850 }
1851
1852 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1853 {
1854   word Info = 0;
1855   word i    = 0;
1856
1857   word selector;
1858   word SSreq;
1859   long relatedPLCIvalue;
1860   DIVA_CAPI_ADAPTER   * relatedadapter;
1861   byte * SSparms  = "";
1862     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1863     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1864   API_PARSE * parms;
1865     API_PARSE ss_parms[11];
1866   PLCI   *rplci;
1867     byte cai[15];
1868   dword d;
1869     API_PARSE dummy;
1870
1871   dbug(1,dprintf("facility_req"));
1872   for(i=0;i<9;i++) ss_parms[i].length = 0;
1873
1874   parms = &msg[1];
1875
1876   if(!a)
1877   {
1878     dbug(1,dprintf("wrong Ctrl"));
1879     Info = _WRONG_IDENTIFIER;
1880   }
1881
1882   selector = GET_WORD(msg[0].info);
1883
1884   if(!Info)
1885   {
1886     switch(selector)
1887     {
1888       case SELECTOR_HANDSET:
1889         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1890         break;
1891
1892       case SELECTOR_SU_SERV:
1893         if(!msg[1].length)
1894         {
1895           Info = _WRONG_MESSAGE_FORMAT;
1896           break;
1897         }
1898         SSreq = GET_WORD(&(msg[1].info[1]));
1899         PUT_WORD(&RCparms[1],SSreq);
1900         SSparms = RCparms;
1901         switch(SSreq)
1902         {
1903           case S_GET_SUPPORTED_SERVICES:
1904             if((i=get_plci(a)))
1905             {
1906               rplci = &a->plci[i-1];
1907               rplci->appl = appl;
1908               add_p(rplci,CAI,"\x01\x80");
1909               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1910               sig_req(rplci,ASSIGN,DSIG_ID);
1911               send_req(rplci);
1912             }
1913             else
1914             {
1915               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1916               SSparms = (byte *)SSstruct;
1917               break;
1918             }
1919             rplci->internal_command = GETSERV_REQ_PEND;
1920             rplci->number = Number;
1921             rplci->appl = appl;
1922             sig_req(rplci,S_SUPPORTED,0);
1923             send_req(rplci);
1924             return false;
1925             break;
1926
1927           case S_LISTEN:
1928             if(parms->length==7)
1929             {
1930               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1931               {
1932                 dbug(1,dprintf("format wrong"));
1933                 Info = _WRONG_MESSAGE_FORMAT;
1934                 break;
1935               }
1936             }
1937             else
1938             {
1939               Info = _WRONG_MESSAGE_FORMAT;
1940               break;
1941             }
1942             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1943             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1944             {
1945               if((i=get_plci(a)))
1946               {
1947                 rplci = &a->plci[i-1];
1948                 rplci->appl = appl;
1949                 add_p(rplci,CAI,"\x01\x80");
1950                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1951                 sig_req(rplci,ASSIGN,DSIG_ID);
1952                 send_req(rplci);
1953               }
1954               else
1955               {
1956                 break;
1957               }
1958               rplci->internal_command = GET_MWI_STATE;
1959               rplci->number = Number;
1960               sig_req(rplci,MWI_POLL,0);
1961               send_req(rplci);
1962             }
1963             break;
1964
1965           case S_HOLD:
1966             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1967             if(plci && plci->State && plci->SuppState==IDLE)
1968             {
1969               plci->SuppState = HOLD_REQUEST;
1970               plci->command = C_HOLD_REQ;
1971               add_s(plci,CAI,&ss_parms[1]);
1972               sig_req(plci,CALL_HOLD,0);
1973               send_req(plci);
1974               return false;
1975             }
1976             else Info = 0x3010;                    /* wrong state           */
1977             break;
1978           case S_RETRIEVE:
1979             if(plci && plci->State && plci->SuppState==CALL_HELD)
1980             {
1981               if(Id & EXT_CONTROLLER)
1982               {
1983                 if(AdvCodecSupport(a, plci, appl, 0))
1984                 {
1985                   Info = 0x3010;                    /* wrong state           */
1986                   break;
1987                 }
1988               }
1989               else plci->tel = 0;
1990
1991               plci->SuppState = RETRIEVE_REQUEST;
1992               plci->command = C_RETRIEVE_REQ;
1993               if(plci->spoofed_msg==SPOOFING_REQUIRED)
1994               {
1995                 plci->spoofed_msg = CALL_RETRIEVE;
1996                 plci->internal_command = BLOCK_PLCI;
1997                 plci->command = 0;
1998                 dbug(1,dprintf("Spoof"));
1999                 return false;
2000               }
2001               else
2002               {
2003                 sig_req(plci,CALL_RETRIEVE,0);
2004                 send_req(plci);
2005                 return false;
2006               }
2007             }
2008             else Info = 0x3010;                    /* wrong state           */
2009             break;
2010           case S_SUSPEND:
2011             if(parms->length)
2012             {
2013               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2014               {
2015                 dbug(1,dprintf("format wrong"));
2016                 Info = _WRONG_MESSAGE_FORMAT;
2017                 break;
2018               }
2019             }
2020             if(plci && plci->State)
2021             {
2022               add_s(plci,CAI,&ss_parms[2]);
2023               plci->command = SUSPEND_REQ;
2024               sig_req(plci,SUSPEND,0);
2025               plci->State = SUSPENDING;
2026               send_req(plci);
2027             }
2028             else Info = 0x3010;                    /* wrong state           */
2029             break;
2030
2031           case S_RESUME:
2032             if(!(i=get_plci(a)) )
2033             {
2034               Info = _OUT_OF_PLCI;
2035               break;
2036             }
2037             rplci = &a->plci[i-1];
2038             rplci->appl = appl;
2039             rplci->number = Number;
2040             rplci->tel = 0;
2041             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2042             /* check 'external controller' bit for codec support */
2043             if(Id & EXT_CONTROLLER)
2044             {
2045               if(AdvCodecSupport(a, rplci, appl, 0) )
2046               {
2047                 rplci->Id = 0;
2048                 Info = 0x300A;
2049                 break;
2050               }
2051             }
2052             if(parms->length)
2053             {
2054               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2055               {
2056                 dbug(1,dprintf("format wrong"));
2057                 rplci->Id = 0;
2058                 Info = _WRONG_MESSAGE_FORMAT;
2059                 break;
2060               }
2061             }
2062             dummy.length = 0;
2063             dummy.info = "\x00";
2064             add_b1(rplci, &dummy, 0, 0);
2065             if (a->Info_Mask[appl->Id-1] & 0x200)
2066             {
2067               /* early B3 connect (CIP mask bit 9) no release after a disc */
2068               add_p(rplci,LLI,"\x01\x01");
2069             }
2070             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2071             sig_req(rplci,ASSIGN,DSIG_ID);
2072             send_req(rplci);
2073             add_s(rplci,CAI,&ss_parms[2]);
2074             rplci->command = RESUME_REQ;
2075             sig_req(rplci,RESUME,0);
2076             rplci->State = RESUMING;
2077             send_req(rplci);
2078             break;
2079
2080           case S_CONF_BEGIN: /* Request */
2081           case S_CONF_DROP:
2082           case S_CONF_ISOLATE:
2083           case S_CONF_REATTACH:
2084             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2085             {
2086               dbug(1,dprintf("format wrong"));
2087               Info = _WRONG_MESSAGE_FORMAT;
2088               break;
2089             }
2090             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2091             {
2092               d = GET_DWORD(ss_parms[2].info);     
2093               if(d>=0x80)
2094               {
2095                 dbug(1,dprintf("format wrong"));
2096                 Info = _WRONG_MESSAGE_FORMAT;
2097                 break;
2098               }
2099               plci->ptyState = (byte)SSreq;
2100               plci->command = 0;
2101               cai[0] = 2;
2102               switch(SSreq)
2103               {
2104               case S_CONF_BEGIN:
2105                   cai[1] = CONF_BEGIN;
2106                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2107                   break;
2108               case S_CONF_DROP:
2109                   cai[1] = CONF_DROP;
2110                   plci->internal_command = CONF_DROP_REQ_PEND;
2111                   break;
2112               case S_CONF_ISOLATE:
2113                   cai[1] = CONF_ISOLATE;
2114                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2115                   break;
2116               case S_CONF_REATTACH:
2117                   cai[1] = CONF_REATTACH;
2118                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2119                   break;
2120               }
2121               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2122               add_p(plci,CAI,cai);
2123               sig_req(plci,S_SERVICE,0);
2124               send_req(plci);
2125               return false;
2126             }
2127             else Info = 0x3010;                    /* wrong state           */
2128             break;
2129
2130           case S_ECT:
2131           case S_3PTY_BEGIN:
2132           case S_3PTY_END:
2133           case S_CONF_ADD:
2134             if(parms->length==7)
2135             {
2136               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2137               {
2138                 dbug(1,dprintf("format wrong"));
2139                 Info = _WRONG_MESSAGE_FORMAT;
2140                 break;
2141               }
2142             }
2143             else if(parms->length==8) /* workaround for the T-View-S */
2144             {
2145               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2146               {
2147                 dbug(1,dprintf("format wrong"));
2148                 Info = _WRONG_MESSAGE_FORMAT;
2149                 break;
2150               }
2151             }
2152             else
2153             {
2154               Info = _WRONG_MESSAGE_FORMAT;
2155               break;
2156             }
2157             if(!msg[1].length)
2158             {
2159               Info = _WRONG_MESSAGE_FORMAT;
2160               break;
2161             }
2162             if (!plci)
2163             {
2164               Info = _WRONG_IDENTIFIER;
2165               break;
2166             }
2167             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2168             relatedPLCIvalue &= 0x0000FFFF;
2169             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2170             /* controller starts with 0 up to (max_adapter - 1) */
2171             if (((relatedPLCIvalue & 0x7f) == 0)
2172              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2173              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2174             {
2175               if(SSreq==S_3PTY_END)
2176               {
2177                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2178                 rplci = plci;
2179               }
2180               else
2181               {
2182                 Info = 0x3010;                    /* wrong state           */
2183                 break;
2184               }
2185             }
2186             else
2187             {  
2188               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2189               relatedPLCIvalue >>=8;
2190               /* find PLCI PTR*/
2191               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2192               {
2193                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2194                 {
2195                   rplci = &relatedadapter->plci[i];
2196                 }
2197               }
2198               if(!rplci || !relatedPLCIvalue)
2199               {
2200                 if(SSreq==S_3PTY_END)
2201                 {
2202                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2203                   rplci = plci;
2204                 }
2205                 else
2206                 {
2207                   Info = 0x3010;                    /* wrong state           */
2208                   break;
2209                 }
2210               }
2211             }
2212 /*
2213             dbug(1,dprintf("rplci:%x",rplci));
2214             dbug(1,dprintf("plci:%x",plci));
2215             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2216             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2217             dbug(1,dprintf("SSreq:%x",SSreq));
2218             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2219             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2220             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2221 */
2222             /* send PTY/ECT req, cannot check all states because of US stuff */
2223             if( !rplci->internal_command && rplci->appl )
2224             {
2225               plci->command = 0;
2226               rplci->relatedPTYPLCI = plci;
2227               plci->relatedPTYPLCI = rplci;
2228               rplci->ptyState = (byte)SSreq;
2229               if(SSreq==S_ECT)
2230               {
2231                 rplci->internal_command = ECT_REQ_PEND;
2232                 cai[1] = ECT_EXECUTE;
2233
2234                 rplci->vswitchstate=0;
2235                 rplci->vsprot=0;
2236                 rplci->vsprotdialect=0;
2237                 plci->vswitchstate=0;
2238                 plci->vsprot=0;
2239                 plci->vsprotdialect=0;
2240
2241               }
2242               else if(SSreq==S_CONF_ADD)
2243               {
2244                 rplci->internal_command = CONF_ADD_REQ_PEND;
2245                 cai[1] = CONF_ADD;
2246               }
2247               else
2248               {
2249                 rplci->internal_command = PTY_REQ_PEND;
2250                 cai[1] = (byte)(SSreq-3);
2251               }
2252               rplci->number = Number;
2253               if(plci!=rplci) /* explicit invocation */
2254               {
2255                 cai[0] = 2;
2256                 cai[2] = plci->Sig.Id;
2257                 dbug(1,dprintf("explicit invocation"));
2258               }
2259               else
2260               {
2261                 dbug(1,dprintf("implicit invocation"));
2262                 cai[0] = 1;
2263               }
2264               add_p(rplci,CAI,cai);
2265               sig_req(rplci,S_SERVICE,0);
2266               send_req(rplci);
2267               return false;
2268             }
2269             else
2270             {
2271               dbug(0,dprintf("Wrong line"));
2272               Info = 0x3010;                    /* wrong state           */
2273               break;
2274             }
2275             break;
2276
2277           case S_CALL_DEFLECTION:
2278             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2279             {
2280               dbug(1,dprintf("format wrong"));
2281               Info = _WRONG_MESSAGE_FORMAT;
2282               break;
2283             }
2284             if (!plci)
2285             {
2286               Info = _WRONG_IDENTIFIER;
2287               break;
2288             }
2289             /* reuse unused screening indicator */
2290             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2291             plci->command = 0;
2292             plci->internal_command = CD_REQ_PEND;
2293             appl->CDEnable = true;
2294             cai[0] = 1;
2295             cai[1] = CALL_DEFLECTION;
2296             add_p(plci,CAI,cai);
2297             add_p(plci,CPN,ss_parms[3].info);
2298             sig_req(plci,S_SERVICE,0);
2299             send_req(plci);
2300             return false;
2301             break;
2302
2303           case S_CALL_FORWARDING_START:
2304             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2305             {
2306               dbug(1,dprintf("format wrong"));
2307               Info = _WRONG_MESSAGE_FORMAT;
2308               break;
2309             }
2310
2311             if((i=get_plci(a)))
2312             {
2313               rplci = &a->plci[i-1];
2314               rplci->appl = appl;
2315               add_p(rplci,CAI,"\x01\x80");
2316               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2317               sig_req(rplci,ASSIGN,DSIG_ID);
2318               send_req(rplci);
2319             }
2320             else
2321             {
2322               Info = _OUT_OF_PLCI;
2323               break;
2324             }
2325
2326             /* reuse unused screening indicator */
2327             rplci->internal_command = CF_START_PEND;
2328             rplci->appl = appl;
2329             rplci->number = Number;
2330             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2331             cai[0] = 2;
2332             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2333             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334             add_p(rplci,CAI,cai);
2335             add_p(rplci,OAD,ss_parms[5].info);
2336             add_p(rplci,CPN,ss_parms[6].info);
2337             sig_req(rplci,S_SERVICE,0);
2338             send_req(rplci);
2339             return false;
2340             break;
2341
2342           case S_INTERROGATE_DIVERSION:
2343           case S_INTERROGATE_NUMBERS:
2344           case S_CALL_FORWARDING_STOP:
2345           case S_CCBS_REQUEST:
2346           case S_CCBS_DEACTIVATE:
2347           case S_CCBS_INTERROGATE:
2348             switch(SSreq)
2349             {
2350             case S_INTERROGATE_NUMBERS:
2351                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2352                 {
2353                   dbug(0,dprintf("format wrong"));
2354                   Info = _WRONG_MESSAGE_FORMAT;
2355                 }
2356                 break;
2357             case S_CCBS_REQUEST:
2358             case S_CCBS_DEACTIVATE:
2359                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2360                 {
2361                   dbug(0,dprintf("format wrong"));
2362                   Info = _WRONG_MESSAGE_FORMAT;
2363                 }
2364                 break;
2365             case S_CCBS_INTERROGATE:
2366                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2367                 {
2368                   dbug(0,dprintf("format wrong"));
2369                   Info = _WRONG_MESSAGE_FORMAT;
2370                 }
2371                 break;
2372             default:
2373             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2374             {
2375               dbug(0,dprintf("format wrong"));
2376               Info = _WRONG_MESSAGE_FORMAT;
2377               break;
2378             }
2379                 break;
2380             }
2381
2382             if(Info) break;
2383             if((i=get_plci(a)))
2384             {
2385               rplci = &a->plci[i-1];
2386               switch(SSreq)
2387               {
2388                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2389                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2390                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2391                   break;
2392                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2393                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2394                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2395                   break;
2396                 case S_CALL_FORWARDING_STOP:
2397                   rplci->internal_command = CF_STOP_PEND;
2398                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2399                   break;
2400                 case S_CCBS_REQUEST:
2401                   cai[1] = CCBS_REQUEST;
2402                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2403                   break;
2404                 case S_CCBS_DEACTIVATE:
2405                   cai[1] = CCBS_DEACTIVATE;
2406                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2407                   break;
2408                 case S_CCBS_INTERROGATE:
2409                   cai[1] = CCBS_INTERROGATE;
2410                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2411                   break;
2412                 default:
2413                   cai[1] = 0;
2414                 break;
2415               }
2416               rplci->appl = appl;
2417               rplci->number = Number;
2418               add_p(rplci,CAI,"\x01\x80");
2419               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2420               sig_req(rplci,ASSIGN,DSIG_ID);
2421               send_req(rplci);
2422             }
2423             else
2424             {
2425               Info = _OUT_OF_PLCI;
2426               break;
2427             }
2428
2429             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2430             switch(SSreq)
2431             {
2432             case S_INTERROGATE_NUMBERS:
2433                 cai[0] = 1;
2434                 add_p(rplci,CAI,cai);
2435                 break;
2436             case S_CCBS_REQUEST:
2437             case S_CCBS_DEACTIVATE:
2438                 cai[0] = 3;
2439                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2440                 add_p(rplci,CAI,cai);
2441                 break;
2442             case S_CCBS_INTERROGATE:
2443                 cai[0] = 3;
2444                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2445                 add_p(rplci,CAI,cai);
2446                 add_p(rplci,OAD,ss_parms[4].info);
2447                 break;
2448             default:
2449             cai[0] = 2;
2450             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2451             add_p(rplci,CAI,cai);
2452             add_p(rplci,OAD,ss_parms[5].info);
2453                 break;
2454             }
2455                         
2456             sig_req(rplci,S_SERVICE,0);
2457             send_req(rplci);
2458             return false;
2459             break;
2460
2461           case S_MWI_ACTIVATE:
2462             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2463             {
2464               dbug(1,dprintf("format wrong"));
2465               Info = _WRONG_MESSAGE_FORMAT;
2466               break;
2467             }
2468             if(!plci)
2469             {                               
2470               if((i=get_plci(a)))
2471               {
2472                 rplci = &a->plci[i-1];
2473                 rplci->appl = appl;
2474                 rplci->cr_enquiry=true;
2475                 add_p(rplci,CAI,"\x01\x80");
2476                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2477                 sig_req(rplci,ASSIGN,DSIG_ID);
2478                 send_req(rplci);
2479               }
2480               else
2481               {
2482                 Info = _OUT_OF_PLCI;
2483                 break;
2484               }
2485             }
2486             else
2487             {
2488               rplci = plci;
2489               rplci->cr_enquiry=false;
2490             }
2491
2492             rplci->command = 0;
2493             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2494             rplci->appl = appl;
2495             rplci->number = Number;
2496
2497             cai[0] = 13;
2498             cai[1] = ACTIVATION_MWI; /* Function */
2499             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2500             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2501             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2502             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2503             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2504             add_p(rplci,CAI,cai);
2505             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2506             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2507             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2508             add_p(rplci,UID,ss_parms[10].info); /* Time */
2509             sig_req(rplci,S_SERVICE,0);
2510             send_req(rplci);
2511             return false;
2512
2513           case S_MWI_DEACTIVATE:
2514             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2515             {
2516               dbug(1,dprintf("format wrong"));
2517               Info = _WRONG_MESSAGE_FORMAT;
2518               break;
2519             }
2520             if(!plci)
2521             {                               
2522               if((i=get_plci(a)))
2523               {
2524                 rplci = &a->plci[i-1];
2525                 rplci->appl = appl;
2526                 rplci->cr_enquiry=true;
2527                 add_p(rplci,CAI,"\x01\x80");
2528                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2529                 sig_req(rplci,ASSIGN,DSIG_ID);
2530                 send_req(rplci);
2531               }
2532               else
2533               {
2534                 Info = _OUT_OF_PLCI;
2535                 break;
2536               }
2537             }
2538             else
2539             {
2540               rplci = plci;
2541               rplci->cr_enquiry=false;
2542             }
2543
2544             rplci->command = 0;
2545             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2546             rplci->appl = appl;
2547             rplci->number = Number;
2548
2549             cai[0] = 5;
2550             cai[1] = DEACTIVATION_MWI; /* Function */
2551             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2552             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2553             add_p(rplci,CAI,cai);
2554             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2555             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2556             sig_req(rplci,S_SERVICE,0);
2557             send_req(rplci);
2558             return false;
2559
2560           default:
2561             Info = 0x300E;  /* not supported */
2562             break;
2563         }
2564         break; /* case SELECTOR_SU_SERV: end */
2565
2566
2567       case SELECTOR_DTMF:
2568         return (dtmf_request (Id, Number, a, plci, appl, msg));
2569
2570
2571
2572       case SELECTOR_LINE_INTERCONNECT:
2573         return (mixer_request (Id, Number, a, plci, appl, msg));
2574
2575
2576
2577       case PRIV_SELECTOR_ECHO_CANCELLER:
2578         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2579         return (ec_request (Id, Number, a, plci, appl, msg));
2580
2581       case SELECTOR_ECHO_CANCELLER:
2582         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2583         return (ec_request (Id, Number, a, plci, appl, msg));
2584
2585
2586       case SELECTOR_V42BIS:
2587       default:
2588         Info = _FACILITY_NOT_SUPPORTED;
2589         break;
2590     } /* end of switch(selector) */
2591   }
2592
2593   dbug(1,dprintf("SendFacRc"));
2594   sendf(appl,
2595         _FACILITY_R|CONFIRM,
2596         Id,
2597         Number,
2598         "wws",Info,selector,SSparms);
2599   return false;
2600 }
2601
2602 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
2603 {
2604   dbug(1,dprintf("facility_res"));
2605   return false;
2606 }
2607
2608 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2609 {
2610   word Info = 0;
2611   byte req;
2612   byte len;
2613   word w;
2614   word fax_control_bits, fax_feature_bits, fax_info_change;
2615   API_PARSE * ncpi;
2616     byte pvc[2];
2617
2618     API_PARSE fax_parms[9];
2619   word i;
2620
2621
2622   dbug(1,dprintf("connect_b3_req"));
2623   if(plci)
2624   {
2625     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2626      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2627     {
2628       Info = _WRONG_STATE;
2629     }
2630     else
2631     {
2632       /* local reply if assign unsuccessfull
2633          or B3 protocol allows only one layer 3 connection
2634            and already connected
2635              or B2 protocol not any LAPD
2636                and connect_b3_req contradicts originate/answer direction */
2637       if (!plci->NL.Id
2638        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2639         && ((plci->channels != 0)
2640          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2641           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2642       {
2643         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2644                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2645         Info = _WRONG_STATE;
2646         sendf(appl,                                                        
2647               _CONNECT_B3_R|CONFIRM,
2648               Id,
2649               Number,
2650               "w",Info);
2651         return false;
2652       }
2653       plci->requested_options_conn = 0;
2654
2655       req = N_CONNECT;
2656       ncpi = &parms[0];
2657       if(plci->B3_prot==2 || plci->B3_prot==3)
2658       {
2659         if(ncpi->length>2)
2660         {
2661           /* check for PVC */
2662           if(ncpi->info[2] || ncpi->info[3])
2663           {
2664             pvc[0] = ncpi->info[3];
2665             pvc[1] = ncpi->info[2];
2666             add_d(plci,2,pvc);
2667             req = N_RESET;
2668           }
2669           else
2670           {
2671             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2672             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2673           }
2674         }
2675       }
2676       else if(plci->B3_prot==5)
2677       {
2678         if (plci->NL.Id && !plci->nl_remove_id)
2679         {
2680           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2681           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2682           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2683            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2684           {
2685             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2686             fax_info_change = false;
2687             if (ncpi->length >= 4)
2688             {
2689               w = GET_WORD(&ncpi->info[3]);
2690               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2691               {
2692                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2693                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2694                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2695                 fax_info_change = true;
2696               }
2697               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2698               if (w & 0x0002)  /* Fax-polling request */
2699                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2700               if ((w & 0x0004) /* Request to send / poll another document */
2701                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2702               {
2703                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2704               }
2705               if (ncpi->length >= 6)
2706               {
2707                 w = GET_WORD(&ncpi->info[5]);
2708                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2709                 {
2710                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2711                   fax_info_change = true;
2712                 }
2713
2714                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2715                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2716                 {
2717                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2718                 }
2719                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2720                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2721                 {
2722                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2723                 }
2724                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2725                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2726                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2727                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2728                 {
2729                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2730                     Info = _WRONG_MESSAGE_FORMAT;
2731                   else
2732                   {
2733                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2735       {
2736                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2737                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2738                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2739       }
2740                     w = fax_parms[4].length;
2741                     if (w > 20)
2742                       w = 20;
2743                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2744                     for (i = 0; i < w; i++)
2745                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2746                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2747                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2748                     w = fax_parms[5].length;
2749                     if (w > 20)
2750                       w = 20;
2751                     plci->fax_connect_info_buffer[len++] = (byte) w;
2752                     for (i = 0; i < w; i++)
2753                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2754                     w = fax_parms[6].length;
2755                     if (w > 20)
2756                       w = 20;
2757                     plci->fax_connect_info_buffer[len++] = (byte) w;
2758                     for (i = 0; i < w; i++)
2759                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2760                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2761                       & (1L << PRIVATE_FAX_NONSTANDARD))
2762       {
2763                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2764         {
2765                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2766                         plci->fax_connect_info_buffer[len++] = 0;
2767         }
2768                       else
2769                       {
2770           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2771             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2772    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2773           for (i = 0; i < fax_parms[7].length; i++)
2774      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2775                       }
2776                     }
2777                   }
2778                 }
2779                 else
2780                 {
2781                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2782                 }
2783                 fax_info_change = true;
2784
2785               }
2786               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2787               {
2788                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2789                 fax_info_change = true;
2790               }
2791             }
2792             if (Info == GOOD)
2793             {
2794               plci->fax_connect_info_length = len;
2795               if (fax_info_change)
2796               {
2797                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2798                 {
2799                   start_internal_command (Id, plci, fax_connect_info_command);
2800                   return false;
2801                 }
2802                 else
2803                 {
2804                   start_internal_command (Id, plci, fax_adjust_b23_command);
2805                   return false;
2806                 }
2807               }
2808             }
2809           }
2810           else  Info = _WRONG_STATE;
2811         }
2812         else  Info = _WRONG_STATE;
2813       }
2814
2815       else if (plci->B3_prot == B3_RTP)
2816       {
2817         plci->internal_req_buffer[0] = ncpi->length + 1;
2818         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2819         for (w = 0; w < ncpi->length; w++)
2820           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2821         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2822         return false;
2823       }
2824
2825       if(!Info)
2826       {
2827         nl_req_ncci(plci,req,0);
2828         return 1;
2829       }
2830     }
2831   }
2832   else Info = _WRONG_IDENTIFIER;
2833
2834   sendf(appl,
2835         _CONNECT_B3_R|CONFIRM,
2836         Id,
2837         Number,
2838         "w",Info);
2839   return false;
2840 }
2841
2842 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2843 {
2844   word ncci;
2845   API_PARSE * ncpi;
2846   byte req;
2847
2848   word w;
2849
2850
2851     API_PARSE fax_parms[9];
2852   word i;
2853   byte len;
2854
2855
2856   dbug(1,dprintf("connect_b3_res"));
2857
2858   ncci = (word)(Id>>16);
2859   if(plci && ncci) {
2860     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2861       if (GET_WORD (&parms[0].info[0]) != 0)
2862       {
2863         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2864         channel_request_xon (plci, a->ncci_ch[ncci]);
2865         channel_xmit_xon (plci);
2866         cleanup_ncci_data (plci, ncci);
2867         nl_req_ncci(plci,N_DISC,(byte)ncci);
2868         return 1;
2869       }
2870       a->ncci_state[ncci] = INC_ACT_PENDING;
2871
2872       req = N_CONNECT_ACK;
2873       ncpi = &parms[1];
2874       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2875       {
2876
2877         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2878           & (1L << PRIVATE_FAX_NONSTANDARD))
2879  {
2880    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2881     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2882     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2883    {
2884             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2885             if (plci->fax_connect_info_length < len)
2886             {
2887               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2888               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2889             }
2890             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2891             {
2892               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2893             }
2894             else
2895             {
2896               if (plci->fax_connect_info_length <= len)
2897                 plci->fax_connect_info_buffer[len] = 0;
2898               len += 1 + plci->fax_connect_info_buffer[len];
2899               if (plci->fax_connect_info_length <= len)
2900                 plci->fax_connect_info_buffer[len] = 0;
2901               len += 1 + plci->fax_connect_info_buffer[len];
2902               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2903                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2904               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2905               for (i = 0; i < fax_parms[7].length; i++)
2906                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2907             }
2908             plci->fax_connect_info_length = len;
2909             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2910             start_internal_command (Id, plci, fax_connect_ack_command);
2911      return false;
2912           }
2913         }
2914
2915         nl_req_ncci(plci,req,(byte)ncci);
2916         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2917          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2918         {
2919           if (plci->B3_prot == 4)
2920             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2921           else
2922             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2923           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2924         }
2925       }
2926
2927       else if (plci->B3_prot == B3_RTP)
2928       {
2929         plci->internal_req_buffer[0] = ncpi->length + 1;
2930         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2931         for (w = 0; w < ncpi->length; w++)
2932           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2933         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2934         return false;
2935       }
2936
2937       else
2938       {
2939         if(ncpi->length>2) {
2940           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2941           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2942         }
2943         nl_req_ncci(plci,req,(byte)ncci);
2944         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2945         if (plci->adjust_b_restore)
2946         {
2947           plci->adjust_b_restore = false;
2948           start_internal_command (Id, plci, adjust_b_restore);
2949         }
2950       }
2951       return 1;
2952     }
2953   }
2954   return false;
2955 }
2956
2957 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2958 {
2959   word ncci;
2960
2961   ncci = (word)(Id>>16);
2962   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2963
2964   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2965    && (plci->State != OUTG_DIS_PENDING))
2966   {
2967     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2968       a->ncci_state[ncci] = CONNECTED;
2969       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2970       channel_request_xon (plci, a->ncci_ch[ncci]);
2971       channel_xmit_xon (plci);
2972     }
2973   }
2974   return false;
2975 }
2976
2977 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2978 {
2979   word Info;
2980   word ncci;
2981   API_PARSE * ncpi;
2982
2983   dbug(1,dprintf("disconnect_b3_req"));
2984
2985   Info = _WRONG_IDENTIFIER;
2986   ncci = (word)(Id>>16);
2987   if (plci && ncci)
2988   {
2989     Info = _WRONG_STATE;
2990     if ((a->ncci_state[ncci] == CONNECTED)
2991      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2992      || (a->ncci_state[ncci] == INC_CON_PENDING)
2993      || (a->ncci_state[ncci] == INC_ACT_PENDING))
2994     {
2995       a->ncci_state[ncci] = OUTG_DIS_PENDING;
2996       channel_request_xon (plci, a->ncci_ch[ncci]);
2997       channel_xmit_xon (plci);
2998
2999       if (a->ncci[ncci].data_pending
3000        && ((plci->B3_prot == B3_TRANSPARENT)
3001         || (plci->B3_prot == B3_T30)
3002         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3003       {
3004         plci->send_disc = (byte)ncci;
3005         plci->command = 0;
3006         return false;
3007       }
3008       else
3009       {
3010         cleanup_ncci_data (plci, ncci);
3011
3012         if(plci->B3_prot==2 || plci->B3_prot==3)
3013         {
3014           ncpi = &parms[0];
3015           if(ncpi->length>3)
3016           {
3017             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3018           }
3019         }
3020         nl_req_ncci(plci,N_DISC,(byte)ncci);
3021       }
3022       return 1;
3023     }
3024   }
3025   sendf(appl,
3026         _DISCONNECT_B3_R|CONFIRM,
3027         Id,
3028         Number,
3029         "w",Info);
3030   return false;
3031 }
3032
3033 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3034 {
3035   word ncci;
3036   word i;
3037
3038   ncci = (word)(Id>>16);
3039   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3040   if(plci && ncci) {
3041     plci->requested_options_conn = 0;
3042     plci->fax_connect_info_length = 0;
3043     plci->ncpi_state = 0x00;
3044     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3045       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3046     {
3047       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3048     }
3049     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3050     if(i<MAX_CHANNELS_PER_PLCI) {
3051       if(plci->channels)plci->channels--;
3052       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3053       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3054
3055       ncci_free_receive_buffers (plci, ncci);
3056
3057       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3058         if(plci->State == SUSPENDING){
3059           sendf(plci->appl,
3060                 _FACILITY_I,
3061                 Id & 0xffffL,
3062                 0,
3063                 "ws", (word)3, "\x03\x04\x00\x00");
3064           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3065         }
3066         plci_remove(plci);
3067         plci->State=IDLE;
3068       }
3069     }
3070     else
3071     {
3072       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3073        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3074        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3075       {
3076         ncci_free_receive_buffers (plci, ncci);
3077
3078         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3079
3080         plci->adapter->ncci_state[ncci] = IDLE;
3081         start_internal_command (Id, plci, fax_disconnect_command);
3082         return 1;
3083       }
3084     }
3085   }
3086   return false;
3087 }
3088
3089 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3090 {
3091   NCCI   *ncci_ptr;
3092   DATA_B3_DESC   *data;
3093   word Info;
3094   word ncci;
3095   word i;
3096
3097   dbug(1,dprintf("data_b3_req"));
3098
3099   Info = _WRONG_IDENTIFIER;
3100   ncci = (word)(Id>>16);
3101   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3102
3103   if (plci && ncci)
3104   {
3105     Info = _WRONG_STATE;
3106     if ((a->ncci_state[ncci] == CONNECTED)
3107      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3108     {
3109         /* queue data */
3110       ncci_ptr = &(a->ncci[ncci]);
3111       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3112       if (i >= MAX_DATA_B3)
3113         i -= MAX_DATA_B3;
3114       data = &(ncci_ptr->DBuffer[i]);
3115       data->Number = Number;
3116       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3117        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3118       {
3119
3120         data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3121
3122       }
3123       else
3124         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3125       data->Length = GET_WORD(parms[1].info);
3126       data->Handle = GET_WORD(parms[2].info);
3127       data->Flags = GET_WORD(parms[3].info);
3128       (ncci_ptr->data_pending)++;
3129
3130         /* check for delivery confirmation */
3131       if (data->Flags & 0x0004)
3132       {
3133         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3134         if (i >= MAX_DATA_ACK)
3135           i -= MAX_DATA_ACK;
3136         ncci_ptr->DataAck[i].Number = data->Number;
3137         ncci_ptr->DataAck[i].Handle = data->Handle;
3138         (ncci_ptr->data_ack_pending)++;
3139       }
3140
3141       send_data(plci);
3142       return false;
3143     }
3144   }
3145   if (appl)
3146   {
3147     if (plci)
3148     {
3149       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3150        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3151       {
3152
3153         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3154
3155       }
3156     }
3157     sendf(appl,
3158           _DATA_B3_R|CONFIRM,
3159           Id,
3160           Number,
3161           "ww",GET_WORD(parms[2].info),Info);
3162   }
3163   return false;
3164 }
3165
3166 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3167 {
3168   word n;
3169   word ncci;
3170   word NCCIcode;
3171
3172   dbug(1,dprintf("data_b3_res"));
3173
3174   ncci = (word)(Id>>16);
3175   if(plci && ncci) {
3176     n = GET_WORD(parms[0].info);
3177     dbug(1,dprintf("free(%d)",n));
3178     NCCIcode = ncci | (((word) a->Id) << 8);
3179     if(n<appl->MaxBuffer &&
3180        appl->DataNCCI[n]==NCCIcode &&
3181        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3182       dbug(1,dprintf("found"));
3183       appl->DataNCCI[n] = 0;
3184
3185       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3186         channel_request_xon (plci, a->ncci_ch[ncci]);
3187       }
3188       channel_xmit_xon (plci);
3189
3190       if(appl->DataFlags[n] &4) {
3191         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3192         return 1;
3193       }
3194     }
3195   }
3196   return false;
3197 }
3198
3199 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3200 {
3201   word Info;
3202   word ncci;
3203
3204   dbug(1,dprintf("reset_b3_req"));
3205
3206   Info = _WRONG_IDENTIFIER;
3207   ncci = (word)(Id>>16);
3208   if(plci && ncci)
3209   {
3210     Info = _WRONG_STATE;
3211     switch (plci->B3_prot)
3212     {
3213     case B3_ISO8208:
3214     case B3_X25_DCE:
3215       if(a->ncci_state[ncci]==CONNECTED)
3216       {
3217         nl_req_ncci(plci,N_RESET,(byte)ncci);
3218         send_req(plci);
3219         Info = GOOD;
3220       }
3221       break;
3222     case B3_TRANSPARENT:
3223       if(a->ncci_state[ncci]==CONNECTED)
3224       {
3225         start_internal_command (Id, plci, reset_b3_command);
3226         Info = GOOD;
3227       }
3228       break;
3229     }
3230   }
3231   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3232   sendf(appl,
3233         _RESET_B3_R|CONFIRM,
3234         Id,
3235         Number,
3236         "w",Info);
3237   return false;
3238 }
3239
3240 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3241 {
3242   word ncci;
3243
3244   dbug(1,dprintf("reset_b3_res"));
3245
3246   ncci = (word)(Id>>16);
3247   if(plci && ncci) {
3248     switch (plci->B3_prot)
3249     {
3250     case B3_ISO8208:
3251     case B3_X25_DCE:
3252       if(a->ncci_state[ncci]==INC_RES_PENDING)
3253       {
3254         a->ncci_state[ncci] = CONNECTED;
3255         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3256         return true;
3257       }
3258     break;
3259     }
3260   }
3261   return false;
3262 }
3263
3264 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3265 {
3266   word ncci;
3267   API_PARSE * ncpi;
3268   byte req;
3269
3270   dbug(1,dprintf("connect_b3_t90_a_res"));
3271
3272   ncci = (word)(Id>>16);
3273   if(plci && ncci) {
3274     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3275       a->ncci_state[ncci] = CONNECTED;
3276     }
3277     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3278       a->ncci_state[ncci] = CONNECTED;
3279
3280       req = N_CONNECT_ACK;
3281
3282         /* parms[0]==0 for CAPI original message definition! */
3283       if(parms[0].info) {
3284         ncpi = &parms[1];
3285         if(ncpi->length>2) {
3286           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3287           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3288         }
3289       }
3290       nl_req_ncci(plci,req,(byte)ncci);
3291       return 1;
3292     }
3293   }
3294   return false;
3295 }
3296
3297
3298 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3299 {
3300   word Info=0;
3301   word i;
3302   byte tel;
3303     API_PARSE bp_parms[7];
3304
3305   if(!plci || !msg)
3306   {
3307     Info = _WRONG_IDENTIFIER;
3308   }
3309   else
3310   {
3311     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3312                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3313     dbug(1,dprintf("PlciState=0x%x",plci->State));
3314     for(i=0;i<7;i++) bp_parms[i].length = 0;
3315
3316     /* check if no channel is open, no B3 connected only */
3317     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3318      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3319     {
3320       Info = _WRONG_STATE;
3321     }
3322     /* check message format and fill bp_parms pointer */
3323     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3324     {
3325       Info = _WRONG_MESSAGE_FORMAT;
3326     }
3327     else
3328     {
3329       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3330       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3331         if(Id & EXT_CONTROLLER)
3332         {
3333           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3334           return 0;
3335         }
3336         plci->State=INC_CON_CONNECTED_ALERT;
3337         plci->appl = appl;
3338         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3339         dump_c_ind_mask (plci);
3340         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3341         {                         /* its quasi a connect        */
3342           if(test_c_ind_mask_bit (plci, i))
3343             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3344         }
3345       }
3346
3347       api_save_msg(msg, "s", &plci->saved_msg);
3348       tel = plci->tel;
3349       if(Id & EXT_CONTROLLER)
3350       {
3351         if(tel) /* external controller in use by this PLCI */
3352         {
3353           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3354           {
3355             dbug(1,dprintf("Ext_Ctrl in use 1"));
3356             Info = _WRONG_STATE;
3357           }
3358         }
3359         else  /* external controller NOT in use by this PLCI ? */
3360         {
3361           if(a->AdvSignalPLCI)
3362           {
3363             dbug(1,dprintf("Ext_Ctrl in use 2"));
3364             Info = _WRONG_STATE;
3365           }
3366           else /* activate the codec */
3367           {
3368             dbug(1,dprintf("Ext_Ctrl start"));
3369             if(AdvCodecSupport(a, plci, appl, 0) )
3370             {
3371               dbug(1,dprintf("Error in codec procedures"));
3372               Info = _WRONG_STATE;
3373             }
3374             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3375             {
3376               plci->spoofed_msg = AWAITING_SELECT_B;
3377               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3378               plci->command = 0;
3379               dbug(1,dprintf("continue if codec loaded"));
3380               return false;
3381             }
3382           }
3383         }
3384       }
3385       else /* external controller bit is OFF */
3386       {
3387         if(tel) /* external controller in use, need to switch off */
3388         {
3389           if(a->AdvSignalAppl==appl)
3390           {
3391             CodecIdCheck(a, plci);
3392             plci->tel = 0;
3393             plci->adv_nl = 0;
3394             dbug(1,dprintf("Ext_Ctrl disable"));
3395           }
3396           else
3397           {
3398             dbug(1,dprintf("Ext_Ctrl not requested"));
3399           }
3400         }
3401       }
3402       if (!Info)
3403       {
3404         if (plci->call_dir & CALL_DIR_OUT)
3405           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3406         else if (plci->call_dir & CALL_DIR_IN)
3407           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3408         start_internal_command (Id, plci, select_b_command);
3409         return false;
3410       }
3411     }
3412   }
3413   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3414   return false;
3415 }
3416
3417 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3418                              PLCI *plci, APPL *appl, API_PARSE *parms)
3419 {
3420   word command;
3421   word i;
3422   word ncci;
3423   API_PARSE * m;
3424     API_PARSE m_parms[5];
3425   word codec;
3426   byte req;
3427   byte ch;
3428   byte dir;
3429   static byte chi[2] = {0x01,0x00};
3430   static byte lli[2] = {0x01,0x00};
3431   static byte codec_cai[2] = {0x01,0x01};
3432   static byte null_msg = {0};
3433   static API_PARSE null_parms = { 0, &null_msg };
3434   PLCI   * v_plci;
3435   word Info=0;
3436
3437   dbug(1,dprintf("manufacturer_req"));
3438   for(i=0;i<5;i++) m_parms[i].length = 0;
3439
3440   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441     Info = _WRONG_MESSAGE_FORMAT;
3442   }
3443   command = GET_WORD(parms[1].info);
3444   m = &parms[2];
3445   if (!Info)
3446   {
3447     switch(command) {
3448     case _DI_ASSIGN_PLCI:
3449       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450         Info = _WRONG_MESSAGE_FORMAT;
3451         break;
3452       }
3453       codec = GET_WORD(m_parms[0].info);
3454       ch = m_parms[1].info[0];
3455       dir = m_parms[2].info[0];
3456       if((i=get_plci(a))) {
3457         plci = &a->plci[i-1];
3458         plci->appl = appl;
3459         plci->command = _MANUFACTURER_R;
3460         plci->m_command = command;
3461         plci->number = Number;
3462         plci->State = LOCAL_CONNECT;
3463         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3465
3466         if((ch==1 || ch==2) && (dir<=2)) {
3467           chi[1] = (byte)(0x80|ch);
3468           lli[1] = 0;
3469           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470           switch(codec)
3471           {
3472           case 0:
3473             Info = add_b1(plci,&m_parms[3],0,0);
3474             break;
3475           case 1:
3476             add_p(plci,CAI,codec_cai);
3477             break;
3478           /* manual 'swich on' to the codec support without signalling */
3479           /* first 'assign plci' with this function, then use */
3480           case 2:
3481             if(AdvCodecSupport(a, plci, appl, 0) ) {
3482               Info = _RESOURCE_ERROR;
3483             }
3484             else {
3485               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486               lli[1] = 0x10; /* local call codec stream */
3487             }
3488             break;
3489           }
3490
3491           plci->State = LOCAL_CONNECT;
3492           plci->manufacturer = true;
3493           plci->command = _MANUFACTURER_R;
3494           plci->m_command = command;
3495           plci->number = Number;
3496
3497           if(!Info)
3498           {
3499             add_p(plci,LLI,lli);
3500             add_p(plci,CHI,chi);
3501             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502             sig_req(plci,ASSIGN,DSIG_ID);
3503
3504             if(!codec)
3505             {
3506               Info = add_b23(plci,&m_parms[3]);
3507               if(!Info)
3508               {
3509                 nl_req_ncci(plci,ASSIGN,0);
3510                 send_req(plci);
3511               }
3512             }
3513             if(!Info)
3514             {
3515               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3517               {
3518                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519                 plci->spoofed_msg = AWAITING_MANUF_CON;
3520                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521                 plci->command = 0;
3522                 send_req(plci);
3523                 return false;
3524               }
3525               if(dir==1) {
3526                 sig_req(plci,CALL_REQ,0);
3527               }
3528               else if(!dir){
3529                 sig_req(plci,LISTEN_REQ,0);
3530               }
3531               send_req(plci);
3532             }
3533             else
3534             {
3535               sendf(appl,
3536                     _MANUFACTURER_R|CONFIRM,
3537                     Id,
3538                     Number,
3539                     "dww",_DI_MANU_ID,command,Info);
3540               return 2;
3541             }
3542           }
3543         }
3544       }
3545       else  Info = _OUT_OF_PLCI;
3546       break;
3547
3548     case _DI_IDI_CTRL:
3549       if(!plci)
3550       {
3551         Info = _WRONG_IDENTIFIER;
3552         break;
3553       }
3554       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555         Info = _WRONG_MESSAGE_FORMAT;
3556         break;
3557       }
3558       req = m_parms[0].info[0];
3559       plci->command = _MANUFACTURER_R;
3560       plci->m_command = command;
3561       plci->number = Number;
3562       if(req==CALL_REQ)
3563       {
3564         plci->b_channel = getChannel(&m_parms[1]);
3565         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3567         {
3568           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570           plci->command = 0;
3571           break;
3572         }
3573       }
3574       else if(req==LAW_REQ)
3575       {
3576         plci->cr_enquiry = true;
3577       }
3578       add_ss(plci,FTY,&m_parms[1]);
3579       sig_req(plci,req,0);
3580       send_req(plci);
3581       if(req==HANGUP)
3582       {      
3583         if (plci->NL.Id && !plci->nl_remove_id)
3584         {
3585           if (plci->channels)
3586           {
3587             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3588             {
3589               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3590               {
3591                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592                 cleanup_ncci_data (plci, ncci);
3593                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3594               }
3595             }
3596           }
3597           mixer_remove (plci);
3598           nl_req_ncci(plci,REMOVE,0);
3599           send_req(plci);
3600         }  
3601       }
3602       break;
3603
3604     case _DI_SIG_CTRL:
3605     /* signalling control for loop activation B-channel */
3606       if(!plci)
3607       {
3608         Info = _WRONG_IDENTIFIER;
3609         break;
3610       }
3611       if(m->length){
3612         plci->command = _MANUFACTURER_R;
3613         plci->number = Number;
3614         add_ss(plci,FTY,m);
3615         sig_req(plci,SIG_CTRL,0);
3616         send_req(plci);
3617       }
3618       else Info = _WRONG_MESSAGE_FORMAT;
3619       break;
3620
3621     case _DI_RXT_CTRL:
3622     /* activation control for receiver/transmitter B-channel */
3623       if(!plci)
3624       {
3625         Info = _WRONG_IDENTIFIER;
3626         break;
3627       }
3628       if(m->length){
3629         plci->command = _MANUFACTURER_R;
3630         plci->number = Number;
3631         add_ss(plci,FTY,m);
3632         sig_req(plci,DSP_CTRL,0);
3633         send_req(plci);
3634       }
3635       else Info = _WRONG_MESSAGE_FORMAT;
3636       break;
3637
3638     case _DI_ADV_CODEC:
3639     case _DI_DSP_CTRL:
3640       /* TEL_CTRL commands to support non standard adjustments: */
3641       /* Ring on/off, Handset micro volume, external micro vol. */
3642       /* handset+external speaker volume, receiver+transm. gain,*/
3643       /* handsfree on (hookinfo off), set mixer command         */
3644
3645       if(command == _DI_ADV_CODEC)
3646       {
3647         if(!a->AdvCodecPLCI) {
3648           Info = _WRONG_STATE;
3649           break;
3650         }
3651         v_plci = a->AdvCodecPLCI;
3652       }
3653       else
3654       {
3655         if (plci
3656          && (m->length >= 3)
3657          && (m->info[1] == 0x1c)
3658          && (m->info[2] >= 1))
3659         {
3660           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3661           {
3662             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3663             {
3664               Info = _WRONG_STATE;
3665               break;
3666             }
3667             a->adv_voice_coef_length = m->info[2] - 1;
3668             if (a->adv_voice_coef_length > m->length - 3)
3669               a->adv_voice_coef_length = (byte)(m->length - 3);
3670             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672             for (i = 0; i < a->adv_voice_coef_length; i++)
3673               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674             if (plci->B1_facilities & B1_FACILITY_VOICE)
3675               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676             break;
3677           }
3678           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3679           {
3680             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3681             {
3682               Info = _FACILITY_NOT_SUPPORTED;
3683               break;
3684             }
3685
3686             plci->dtmf_parameter_length = m->info[2] - 1;
3687             if (plci->dtmf_parameter_length > m->length - 3)
3688               plci->dtmf_parameter_length = (byte)(m->length - 3);
3689             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691             for (i = 0; i < plci->dtmf_parameter_length; i++)
3692               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694               dtmf_parameter_write (plci);
3695             break;
3696
3697           }
3698         }
3699         v_plci = plci;
3700       }
3701
3702       if(!v_plci)
3703       {
3704         Info = _WRONG_IDENTIFIER;
3705         break;
3706       }
3707       if(m->length){
3708         add_ss(v_plci,FTY,m);
3709         sig_req(v_plci,TEL_CTRL,0);
3710         send_req(v_plci);
3711       }
3712       else Info = _WRONG_MESSAGE_FORMAT;
3713
3714       break;
3715
3716     case _DI_OPTIONS_REQUEST:
3717       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718         Info = _WRONG_MESSAGE_FORMAT;
3719         break;
3720       }
3721       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3722       {
3723         Info = _FACILITY_NOT_SUPPORTED;
3724         break;
3725       }
3726       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727       break;
3728
3729
3730
3731     default:
3732       Info = _WRONG_MESSAGE_FORMAT;
3733       break;
3734     }
3735   }
3736
3737   sendf(appl,
3738         _MANUFACTURER_R|CONFIRM,
3739         Id,
3740         Number,
3741         "dww",_DI_MANU_ID,command,Info);
3742   return false;
3743 }
3744
3745
3746 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3747                              PLCI *plci, APPL *appl, API_PARSE *msg)
3748 {
3749   word indication;
3750
3751     API_PARSE m_parms[3];
3752   API_PARSE *ncpi;
3753     API_PARSE fax_parms[9];
3754   word i;
3755   byte len;
3756
3757
3758   dbug(1,dprintf("manufacturer_res"));
3759
3760   if ((msg[0].length == 0)
3761    || (msg[1].length == 0)
3762    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3763   {
3764     return false;
3765   }
3766   indication = GET_WORD(msg[1].info);
3767   switch (indication)
3768   {
3769
3770   case _DI_NEGOTIATE_B3:
3771     if(!plci)
3772       break;
3773     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3774      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3775     {
3776       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3777       break;
3778     }
3779     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3780     {
3781       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3782       break;
3783     }
3784     ncpi = &m_parms[1];
3785     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3786     if (plci->fax_connect_info_length < len)
3787     {
3788       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3789       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3790     }
3791     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3792     {
3793       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3794     }
3795     else
3796     {
3797       if (plci->fax_connect_info_length <= len)
3798         plci->fax_connect_info_buffer[len] = 0;
3799       len += 1 + plci->fax_connect_info_buffer[len];
3800       if (plci->fax_connect_info_length <= len)
3801         plci->fax_connect_info_buffer[len] = 0;
3802       len += 1 + plci->fax_connect_info_buffer[len];
3803       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3804         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3805       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3806       for (i = 0; i < fax_parms[7].length; i++)
3807         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3808     }
3809     plci->fax_connect_info_length = len;
3810     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3811     start_internal_command (Id, plci, fax_edata_ack_command);
3812     break;
3813
3814   }
3815   return false;
3816 }
3817
3818 /*------------------------------------------------------------------*/
3819 /* IDI callback function                                            */
3820 /*------------------------------------------------------------------*/
3821
3822 void   callback(ENTITY   * e)
3823 {
3824   DIVA_CAPI_ADAPTER   * a;
3825   APPL   * appl;
3826   PLCI   * plci;
3827   CAPI_MSG   *m;
3828   word i, j;
3829   byte rc;
3830   byte ch;
3831   byte req;
3832   byte global_req;
3833   int no_cancel_rc;
3834
3835   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3836                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3837
3838   a = &(adapter[(byte)e->user[0]]);
3839   plci = &(a->plci[e->user[1]]);
3840   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3841
3842   /*
3843      If new protocol code and new XDI is used then CAPI should work
3844      fully in accordance with IDI cpec an look on callback field instead
3845      of Rc field for return codes.
3846    */
3847   if (((e->complete == 0xff) && no_cancel_rc) ||
3848       (e->Rc && !no_cancel_rc)) {
3849     rc = e->Rc;
3850     ch = e->RcCh;
3851     req = e->Req;
3852     e->Rc = 0;
3853
3854     if (e->user[0] & 0x8000)
3855     {
3856       /*
3857          If REMOVE request was sent then we have to wait until
3858          return code with Id set to zero arrives.
3859          All other return codes should be ignored.
3860          */
3861       if (req == REMOVE)
3862       {
3863         if (e->Id)
3864         {
3865           dbug(1,dprintf("cancel RC in REMOVE state"));
3866           return;
3867         }
3868         channel_flow_control_remove (plci);
3869         for (i = 0; i < 256; i++)
3870         {
3871           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3872             a->FlowControlIdTable[i] = 0;
3873         }
3874         plci->nl_remove_id = 0;
3875         if (plci->rx_dma_descriptor > 0) {
3876           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3877           plci->rx_dma_descriptor = 0;
3878         }
3879       }
3880       if (rc == OK_FC)
3881       {
3882         a->FlowControlIdTable[ch] = e->Id;
3883         a->FlowControlSkipTable[ch] = 0;
3884
3885         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3886         a->ch_flow_plci[ch] = plci->Id;
3887         plci->nl_req = 0;
3888       }
3889       else
3890       {
3891         /*
3892           Cancel return codes self, if feature was requested
3893           */
3894         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3895           a->FlowControlIdTable[ch] = 0;
3896           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3897             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3898             return;
3899           }
3900         }
3901
3902         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3903         {
3904           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3905           if (ch == e->ReqCh)
3906             plci->nl_req = 0;
3907         }
3908         else
3909           plci->nl_req = 0;
3910       }
3911       if (plci->nl_req)
3912         control_rc (plci, 0, rc, ch, 0, true);
3913       else
3914       {
3915         if (req == N_XON)
3916         {
3917           channel_x_on (plci, ch);
3918           if (plci->internal_command)
3919             control_rc (plci, req, rc, ch, 0, true);
3920         }
3921         else
3922         {
3923           if (plci->nl_global_req)
3924           {
3925             global_req = plci->nl_global_req;
3926             plci->nl_global_req = 0;
3927             if (rc != ASSIGN_OK) {
3928               e->Id = 0;
3929               if (plci->rx_dma_descriptor > 0) {
3930                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3931                 plci->rx_dma_descriptor = 0;
3932               }
3933             }
3934             channel_xmit_xon (plci);
3935             control_rc (plci, 0, rc, ch, global_req, true);
3936           }
3937           else if (plci->data_sent)
3938           {
3939             channel_xmit_xon (plci);
3940             plci->data_sent = false;
3941             plci->NL.XNum = 1;
3942             data_rc (plci, ch);
3943             if (plci->internal_command)
3944               control_rc (plci, req, rc, ch, 0, true);
3945           }
3946           else
3947           {
3948             channel_xmit_xon (plci);
3949             control_rc (plci, req, rc, ch, 0, true);
3950           }
3951         }
3952       }
3953     }
3954     else
3955     {
3956       /*
3957          If REMOVE request was sent then we have to wait until
3958          return code with Id set to zero arrives.
3959          All other return codes should be ignored.
3960          */
3961       if (req == REMOVE)
3962       {
3963         if (e->Id)
3964         {
3965           dbug(1,dprintf("cancel RC in REMOVE state"));
3966           return;
3967         }
3968         plci->sig_remove_id = 0;
3969       }
3970       plci->sig_req = 0;
3971       if (plci->sig_global_req)
3972       {
3973         global_req = plci->sig_global_req;
3974         plci->sig_global_req = 0;
3975         if (rc != ASSIGN_OK)
3976           e->Id = 0;
3977         channel_xmit_xon (plci);
3978         control_rc (plci, 0, rc, ch, global_req, false);
3979       }
3980       else
3981       {
3982         channel_xmit_xon (plci);
3983         control_rc (plci, req, rc, ch, 0, false);
3984       }
3985     }
3986     /*
3987       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3988       same callback. Also if new XDI and protocol code used then jump
3989       direct to finish.
3990       */
3991     if (no_cancel_rc) {
3992       channel_xmit_xon(plci);
3993       goto capi_callback_suffix;
3994     }
3995   }
3996
3997   channel_xmit_xon(plci);
3998
3999   if (e->Ind) {
4000     if (e->user[0] &0x8000) {
4001       byte Ind = e->Ind & 0x0f;
4002       byte Ch = e->IndCh;
4003       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4004           (a->ch_flow_plci[Ch] == plci->Id)) {
4005         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4006           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4007         }
4008         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4009       }
4010       nl_ind(plci);
4011       if ((e->RNR != 1) &&
4012           (a->ch_flow_plci[Ch] == plci->Id) &&
4013           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4014         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4015         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4016       }
4017     } else {
4018       sig_ind(plci);
4019     }
4020     e->Ind = 0;
4021   }
4022
4023 capi_callback_suffix:
4024
4025   while (!plci->req_in
4026    && !plci->internal_command
4027    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4028   {
4029     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4030
4031     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4032
4033     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4034     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4035     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4036       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4037     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4038     {
4039       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4040       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4041     }
4042     else
4043     {
4044       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4045     }
4046     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4047     {
4048       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4049       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4050     }
4051     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4052     {
4053       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4054       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4055     }
4056     i = api_put (appl, m);
4057     if (i != 0)
4058     {
4059       if (m->header.command == _DATA_B3_R)
4060
4061         TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4062
4063       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4064       break;
4065     }
4066
4067     if (plci->li_notify_update)
4068     {
4069       plci->li_notify_update = false;
4070       mixer_notify_update (plci, false);
4071     }
4072
4073   }
4074   send_data(plci);
4075   send_req(plci);
4076 }
4077
4078
4079 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4080                        byte nl_rc)
4081 {
4082   dword Id;
4083   dword rId;
4084   word Number;
4085   word Info=0;
4086   word i;
4087   word ncci;
4088   DIVA_CAPI_ADAPTER   * a;
4089   APPL   * appl;
4090   PLCI   * rplci;
4091     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4092     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4093
4094   if (!plci) {
4095     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4096     return;
4097   }
4098   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4099   if(plci->req_in!=plci->req_out)
4100   {
4101     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4102     {
4103       dbug(1,dprintf("req_1return"));
4104       return;
4105     }
4106     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4107   }
4108   plci->req_in = plci->req_in_start = plci->req_out = 0;
4109   dbug(1,dprintf("control_rc"));
4110
4111   appl = plci->appl;
4112   a = plci->adapter;
4113   ncci = a->ch_ncci[ch];
4114   if(appl)
4115   {
4116     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4117     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4118     Number = plci->number;
4119     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));
4120     dbug(1,dprintf("channels=0x%x",plci->channels));
4121     if (plci_remove_check(plci))
4122       return;
4123     if(req==REMOVE && rc==ASSIGN_OK)
4124     {
4125       sig_req(plci,HANGUP,0);
4126       sig_req(plci,REMOVE,0);
4127       send_req(plci);
4128     }
4129     if(plci->command)
4130     {
4131       switch(plci->command)
4132       {
4133       case C_HOLD_REQ:
4134         dbug(1,dprintf("HoldRC=0x%x",rc));
4135         SSparms[1] = (byte)S_HOLD;
4136         if(rc!=OK)
4137         {
4138           plci->SuppState = IDLE;
4139           Info = 0x2001;
4140         }
4141         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4142         break;
4143
4144       case C_RETRIEVE_REQ:
4145         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4146         SSparms[1] = (byte)S_RETRIEVE;
4147         if(rc!=OK)
4148         {
4149           plci->SuppState = CALL_HELD;
4150           Info = 0x2001;
4151         }
4152         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4153         break;
4154
4155       case _INFO_R:
4156         dbug(1,dprintf("InfoRC=0x%x",rc));
4157         if(rc!=OK) Info=_WRONG_STATE;
4158         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4159         break;
4160
4161       case _CONNECT_R:
4162         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4163         if (plci->State == INC_DIS_PENDING)
4164           break;
4165         if(plci->Sig.Id!=0xff)
4166         {
4167           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4168            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4169           {
4170             dbug(1,dprintf("No more IDs/Call_Req failed"));
4171             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4172             plci_remove(plci);
4173             plci->State = IDLE;
4174             break;
4175           }
4176           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4177           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4178         }
4179         else /* D-ch activation */
4180         {
4181           if (rc != ASSIGN_OK)
4182           {
4183             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4184             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4185             plci_remove(plci);
4186             plci->State = IDLE;
4187             break;
4188           }
4189           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4190           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4191           plci->State = INC_ACT_PENDING;
4192         }
4193         break;
4194
4195       case _CONNECT_I|RESPONSE:
4196         if (plci->State != INC_DIS_PENDING)
4197           plci->State = INC_CON_ACCEPT;
4198         break;
4199
4200       case _DISCONNECT_R:
4201         if (plci->State == INC_DIS_PENDING)
4202           break;
4203         if(plci->Sig.Id!=0xff)
4204         {
4205           plci->State = OUTG_DIS_PENDING;
4206           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4207         }
4208         break;
4209
4210       case SUSPEND_REQ:
4211         break;
4212
4213       case RESUME_REQ:
4214         break;
4215
4216       case _CONNECT_B3_R:
4217         if(rc!=OK)
4218         {
4219           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4220           break;
4221         }
4222         ncci = get_ncci (plci, ch, 0);
4223         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4224         plci->channels++;
4225         if(req==N_RESET)
4226         {
4227           a->ncci_state[ncci] = INC_ACT_PENDING;
4228           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4229           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4230         }
4231         else
4232         {
4233           a->ncci_state[ncci] = OUTG_CON_PENDING;
4234           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4235         }
4236         break;
4237
4238       case _CONNECT_B3_I|RESPONSE:
4239         break;
4240
4241       case _RESET_B3_R:
4242 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4243         break;
4244
4245       case _DISCONNECT_B3_R:
4246         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4247         break;
4248
4249       case _MANUFACTURER_R:
4250         break;
4251
4252       case PERM_LIST_REQ:
4253         if(rc!=OK)
4254         {
4255           Info = _WRONG_IDENTIFIER;
4256           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4257           plci_remove(plci);
4258         }
4259         else
4260           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4261         break;
4262
4263       default:
4264         break;
4265       }
4266       plci->command = 0;
4267     }
4268     else if (plci->internal_command)
4269     {
4270       switch(plci->internal_command)
4271       {
4272       case BLOCK_PLCI:
4273         return;
4274
4275       case GET_MWI_STATE:
4276         if(rc==OK) /* command supported, wait for indication */
4277         {
4278           return;
4279         }
4280         plci_remove(plci);
4281         break;
4282
4283         /* Get Supported Services */
4284       case GETSERV_REQ_PEND:
4285         if(rc==OK) /* command supported, wait for indication */
4286         {
4287           break;
4288         }
4289         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4290         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4291         plci_remove(plci);
4292         break;
4293
4294       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4295       case INTERR_NUMBERS_REQ_PEND:
4296       case CF_START_PEND:                  /* Call Forwarding Start pending */
4297       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4298       case CCBS_REQUEST_REQ_PEND:
4299       case CCBS_DEACTIVATE_REQ_PEND:
4300       case CCBS_INTERROGATE_REQ_PEND:
4301         switch(plci->internal_command)
4302         {
4303           case INTERR_DIVERSION_REQ_PEND:
4304             SSparms[1] = S_INTERROGATE_DIVERSION;
4305             break;
4306           case INTERR_NUMBERS_REQ_PEND:
4307             SSparms[1] = S_INTERROGATE_NUMBERS;
4308             break;
4309           case CF_START_PEND:
4310             SSparms[1] = S_CALL_FORWARDING_START;
4311             break;
4312           case CF_STOP_PEND:
4313             SSparms[1] = S_CALL_FORWARDING_STOP;
4314             break;
4315           case CCBS_REQUEST_REQ_PEND:
4316             SSparms[1] = S_CCBS_REQUEST;
4317             break;
4318           case CCBS_DEACTIVATE_REQ_PEND:
4319             SSparms[1] = S_CCBS_DEACTIVATE;
4320             break;
4321           case CCBS_INTERROGATE_REQ_PEND:
4322             SSparms[1] = S_CCBS_INTERROGATE;
4323             break;
4324         }
4325         if(global_req==ASSIGN)
4326         {
4327           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4328           return;
4329         }
4330         if(!plci->appl) break;
4331         if(rc==ISDN_GUARD_REJ)
4332         {
4333           Info = _CAPI_GUARD_ERROR;
4334         }
4335         else if(rc!=OK)
4336         {
4337           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4338         }
4339         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4340               plci->number,"wws",Info,(word)3,SSparms);
4341         if(Info) plci_remove(plci);
4342         break;
4343
4344         /* 3pty conference pending */
4345       case PTY_REQ_PEND:
4346         if(!plci->relatedPTYPLCI) break;
4347         rplci = plci->relatedPTYPLCI;
4348         SSparms[1] = plci->ptyState;
4349         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4350         if(rplci->tel) rId|=EXT_CONTROLLER;
4351         if(rc!=OK)
4352         {
4353           Info = 0x300E; /* not supported */
4354           plci->relatedPTYPLCI = NULL;
4355           plci->ptyState = 0;
4356         }
4357         sendf(rplci->appl,
4358               _FACILITY_R|CONFIRM,
4359               rId,
4360               plci->number,
4361               "wws",Info,(word)3,SSparms);
4362         break;
4363
4364         /* Explicit Call Transfer pending */
4365       case ECT_REQ_PEND:
4366         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4367         if(!plci->relatedPTYPLCI) break;
4368         rplci = plci->relatedPTYPLCI;
4369         SSparms[1] = S_ECT;
4370         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4371         if(rplci->tel) rId|=EXT_CONTROLLER;
4372         if(rc!=OK)
4373         {
4374           Info = 0x300E; /* not supported */
4375           plci->relatedPTYPLCI = NULL;
4376           plci->ptyState = 0;
4377         }
4378         sendf(rplci->appl,
4379               _FACILITY_R|CONFIRM,
4380               rId,
4381               plci->number,
4382               "wws",Info,(word)3,SSparms);
4383         break;
4384
4385       case _MANUFACTURER_R:
4386         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4387         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4388         {
4389           dbug(1,dprintf("No more IDs"));
4390           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4391           plci_remove(plci);  /* after codec init, internal codec commands pending */
4392         }
4393         break;
4394
4395       case _CONNECT_R:
4396         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4397         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4398         {
4399           dbug(1,dprintf("No more IDs"));
4400           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4401           plci_remove(plci);  /* after codec init, internal codec commands pending */
4402         }
4403         break;
4404
4405       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4406         return;
4407
4408       case PERM_COD_CALL:
4409         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4410         plci->internal_command = PERM_COD_CONN_PEND;
4411         return;
4412
4413       case PERM_COD_ASSIGN:
4414         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4415         if(rc!=ASSIGN_OK) break;
4416         sig_req(plci,CALL_REQ,0);
4417         send_req(plci);
4418         plci->internal_command = PERM_COD_CALL;
4419         return;
4420
4421         /* Null Call Reference Request pending */
4422       case C_NCR_FAC_REQ:
4423         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4424         if(global_req==ASSIGN)
4425         {
4426           if(rc==ASSIGN_OK)
4427           {
4428             return;
4429           }
4430           else
4431           {
4432             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4433             appl->NullCREnable = false;
4434             plci_remove(plci);
4435           }
4436         }
4437         else if(req==NCR_FACILITY)
4438         {
4439           if(rc==OK)
4440           {
4441             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4442           }
4443           else
4444           {
4445             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4446             appl->NullCREnable = false;
4447           }
4448           plci_remove(plci);
4449         }
4450         break;
4451
4452       case HOOK_ON_REQ:
4453         if(plci->channels)
4454         {
4455           if(a->ncci_state[ncci]==CONNECTED)
4456           {
4457             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4458             cleanup_ncci_data (plci, ncci);
4459             nl_req_ncci(plci,N_DISC,(byte)ncci);
4460           }
4461           break;
4462         }
4463         break;
4464
4465       case HOOK_OFF_REQ:
4466         if (plci->State == INC_DIS_PENDING)
4467           break;
4468         sig_req(plci,CALL_REQ,0);
4469         send_req(plci);
4470         plci->State=OUTG_CON_PENDING;
4471         break;
4472
4473
4474       case MWI_ACTIVATE_REQ_PEND:
4475       case MWI_DEACTIVATE_REQ_PEND:
4476         if(global_req == ASSIGN && rc==ASSIGN_OK)
4477         {
4478           dbug(1,dprintf("MWI_REQ assigned"));
4479           return;
4480         }
4481         else if(rc!=OK)
4482         {                 
4483           if(rc==WRONG_IE)
4484           {
4485             Info = 0x2007; /* Illegal message parameter coding */
4486             dbug(1,dprintf("MWI_REQ invalid parameter"));
4487           }
4488           else
4489           {
4490             Info = 0x300B; /* not supported */                      
4491             dbug(1,dprintf("MWI_REQ not supported"));
4492           }
4493           /* 0x3010: Request not allowed in this state */
4494           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4495                     
4496         }
4497         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4498         {
4499           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4500         }
4501         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4502
4503         if(plci->cr_enquiry)
4504         {
4505           sendf(plci->appl,
4506                 _FACILITY_R|CONFIRM,
4507                 Id&0xf,
4508                 plci->number,
4509                 "wws",Info,(word)3,SSparms);
4510           if(rc!=OK) plci_remove(plci);
4511         }
4512         else
4513         {
4514           sendf(plci->appl,
4515                 _FACILITY_R|CONFIRM,
4516                 Id,
4517                 plci->number,
4518                 "wws",Info,(word)3,SSparms);
4519         }
4520         break;
4521
4522       case CONF_BEGIN_REQ_PEND:
4523       case CONF_ADD_REQ_PEND:
4524       case CONF_SPLIT_REQ_PEND:
4525       case CONF_DROP_REQ_PEND:
4526       case CONF_ISOLATE_REQ_PEND:
4527       case CONF_REATTACH_REQ_PEND:
4528         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4529         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4530         rplci = plci;
4531         rId = Id;
4532         switch(plci->internal_command)
4533         {
4534           case CONF_BEGIN_REQ_PEND:
4535             SSparms[1] = S_CONF_BEGIN;
4536             break;
4537           case CONF_ADD_REQ_PEND:
4538             SSparms[1] = S_CONF_ADD;
4539             rplci = plci->relatedPTYPLCI;
4540             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4541             break;
4542           case CONF_SPLIT_REQ_PEND:
4543             SSparms[1] = S_CONF_SPLIT;
4544             break;
4545           case CONF_DROP_REQ_PEND:
4546             SSparms[1] = S_CONF_DROP;
4547             break;
4548           case CONF_ISOLATE_REQ_PEND:
4549             SSparms[1] = S_CONF_ISOLATE;
4550             break;
4551           case CONF_REATTACH_REQ_PEND:
4552             SSparms[1] = S_CONF_REATTACH;
4553             break;
4554         }
4555         
4556         if(rc!=OK)
4557         {
4558           Info = 0x300E; /* not supported */
4559           plci->relatedPTYPLCI = NULL;
4560           plci->ptyState = 0;
4561         }
4562         sendf(rplci->appl,
4563               _FACILITY_R|CONFIRM,
4564               rId,
4565               plci->number,
4566               "wws",Info,(word)3,SSparms);
4567         break;
4568
4569       case VSWITCH_REQ_PEND:
4570         if(rc!=OK)
4571         {
4572           if(plci->relatedPTYPLCI)
4573           {
4574             plci->relatedPTYPLCI->vswitchstate=0;
4575             plci->relatedPTYPLCI->vsprot=0;
4576             plci->relatedPTYPLCI->vsprotdialect=0;    
4577           }
4578           plci->vswitchstate=0;
4579           plci->vsprot=0;
4580           plci->vsprotdialect=0;
4581         }
4582         else
4583         {
4584           if(plci->relatedPTYPLCI &&
4585              plci->vswitchstate==1 &&
4586              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4587             plci->vswitchstate=3;
4588         }
4589         break;
4590
4591   /* Call Deflection Request pending (SSCT) */
4592       case CD_REQ_PEND:
4593         SSparms[1] = S_CALL_DEFLECTION;
4594         if(rc!=OK)
4595         {
4596           Info = 0x300E; /* not supported */
4597           plci->appl->CDEnable = 0;
4598         }  
4599         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4600           plci->number,"wws",Info,(word)3,SSparms);
4601         break;
4602
4603       case RTP_CONNECT_B3_REQ_COMMAND_2:
4604         if (rc == OK)
4605         {
4606           ncci = get_ncci (plci, ch, 0);
4607           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4608           plci->channels++;
4609           a->ncci_state[ncci] = OUTG_CON_PENDING;
4610         }
4611
4612       default:
4613         if (plci->internal_command_queue[0])
4614         {
4615           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4616           if (plci->internal_command)
4617             return;
4618         }
4619         break;
4620       }
4621       next_internal_command (Id, plci);
4622     }
4623   }
4624   else /* appl==0 */
4625   {
4626     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4627     if(plci->tel) Id|=EXT_CONTROLLER;
4628
4629     switch(plci->internal_command)
4630     {
4631     case BLOCK_PLCI:
4632       return;
4633
4634     case START_L1_SIG_ASSIGN_PEND:
4635     case REM_L1_SIG_ASSIGN_PEND:
4636       if(global_req == ASSIGN)
4637       {
4638         break;
4639       }
4640       else
4641       {
4642         dbug(1,dprintf("***L1 Req rem PLCI"));
4643         plci->internal_command = 0;
4644         sig_req(plci,REMOVE,0);
4645         send_req(plci);
4646       }
4647       break;
4648
4649       /* Call Deflection Request pending, just no appl ptr assigned */
4650     case CD_REQ_PEND:
4651       SSparms[1] = S_CALL_DEFLECTION;
4652       if(rc!=OK)
4653       {
4654         Info = 0x300E; /* not supported */
4655       }
4656       for(i=0; i<max_appl; i++)
4657       {
4658         if(application[i].CDEnable)
4659         {
4660           if(!application[i].Id) application[i].CDEnable = 0;
4661           else
4662           {
4663             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4664                   plci->number,"wws",Info,(word)3,SSparms);
4665             if(Info) application[i].CDEnable = 0;
4666           }
4667         }
4668       }
4669       plci->internal_command = 0;
4670       break;
4671
4672     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4673       return;
4674
4675     case PERM_COD_CALL:
4676       plci->internal_command = PERM_COD_CONN_PEND;
4677       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4678       return;
4679
4680     case PERM_COD_ASSIGN:
4681       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4682       plci->internal_command = 0;
4683       if(rc!=ASSIGN_OK) break;
4684       plci->internal_command = PERM_COD_CALL;
4685       sig_req(plci,CALL_REQ,0);
4686       send_req(plci);
4687       return;
4688
4689     case LISTEN_SIG_ASSIGN_PEND:
4690       if(rc == ASSIGN_OK)
4691       {
4692         plci->internal_command = 0;
4693         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4694         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4695         sig_req(plci,INDICATE_REQ,0);
4696         send_req(plci);
4697       }
4698       else
4699       {
4700         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4701         a->listen_active--;
4702         plci_remove(plci);
4703         plci->State = IDLE;
4704       }
4705       break;
4706
4707     case USELAW_REQ:
4708       if(global_req == ASSIGN)
4709       {
4710         if (rc==ASSIGN_OK)
4711       {
4712         sig_req(plci,LAW_REQ,0);
4713         send_req(plci);
4714         dbug(1,dprintf("Auto-Law assigned"));
4715         }
4716         else
4717         {
4718           dbug(1,dprintf("Auto-Law assign failed"));
4719           a->automatic_law = 3;
4720           plci->internal_command = 0;
4721           a->automatic_lawPLCI = NULL;
4722         }
4723         break;
4724       }
4725       else if(req == LAW_REQ && rc==OK)
4726       {
4727         dbug(1,dprintf("Auto-Law initiated"));
4728         a->automatic_law = 2;
4729         plci->internal_command = 0;
4730       }
4731       else
4732       {
4733         dbug(1,dprintf("Auto-Law not supported"));
4734         a->automatic_law = 3;
4735         plci->internal_command = 0;
4736         sig_req(plci,REMOVE,0);
4737         send_req(plci);
4738         a->automatic_lawPLCI = NULL;
4739       }
4740       break;
4741     }
4742     plci_remove_check(plci);
4743   }
4744 }
4745
4746 static void data_rc(PLCI *plci, byte ch)
4747 {
4748   dword Id;
4749   DIVA_CAPI_ADAPTER   * a;
4750   NCCI   *ncci_ptr;
4751   DATA_B3_DESC   *data;
4752   word ncci;
4753
4754   if (plci->appl)
4755   {
4756     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4757     a = plci->adapter;
4758     ncci = a->ch_ncci[ch];
4759     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4760     {
4761       ncci_ptr = &(a->ncci[ncci]);
4762       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4763       if (ncci_ptr->data_pending)
4764       {
4765         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4766         if (!(data->Flags &4) && a->ncci_state[ncci])
4767         {
4768           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4769           if(plci->tel) Id|=EXT_CONTROLLER;
4770           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4771                 "ww",data->Handle,0);
4772         }
4773         (ncci_ptr->data_out)++;
4774         if (ncci_ptr->data_out == MAX_DATA_B3)
4775           ncci_ptr->data_out = 0;
4776         (ncci_ptr->data_pending)--;
4777       }
4778     }
4779   }
4780 }
4781
4782 static void data_ack(PLCI *plci, byte ch)
4783 {
4784   dword Id;
4785   DIVA_CAPI_ADAPTER   * a;
4786   NCCI   *ncci_ptr;
4787   word ncci;
4788
4789   a = plci->adapter;
4790   ncci = a->ch_ncci[ch];
4791   ncci_ptr = &(a->ncci[ncci]);
4792   if (ncci_ptr->data_ack_pending)
4793   {
4794     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4795     {
4796       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4797       if(plci->tel) Id|=EXT_CONTROLLER;
4798       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4799             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4800     }
4801     (ncci_ptr->data_ack_out)++;
4802     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4803       ncci_ptr->data_ack_out = 0;
4804     (ncci_ptr->data_ack_pending)--;
4805   }
4806 }
4807
4808 static void sig_ind(PLCI *plci)
4809 {
4810   dword x_Id;
4811   dword Id;
4812   dword rId;
4813   word Number = 0;
4814   word i;
4815   word cip;
4816   dword cip_mask;
4817   byte   *ie;
4818   DIVA_CAPI_ADAPTER   * a;
4819     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4820 #define MAXPARMSIDS 31
4821     byte   * parms[MAXPARMSIDS];
4822     byte   * add_i[4];
4823     byte   * multi_fac_parms[MAX_MULTI_IE];
4824     byte   * multi_pi_parms [MAX_MULTI_IE];
4825     byte   * multi_ssext_parms [MAX_MULTI_IE];
4826     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4827
4828     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4829
4830   byte ai_len;
4831     byte   *esc_chi = "";
4832     byte   *esc_law = "";
4833     byte   *pty_cai = "";
4834     byte   *esc_cr  = "";
4835     byte   *esc_profile = "";
4836
4837     byte facility[256];
4838   PLCI   * tplci = NULL;
4839   byte chi[] = "\x02\x18\x01";
4840   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4841     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4842   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4843   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4844   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4845   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4846     word parms_id[] =
4847          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4848           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4849           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4850           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4851           /* 14 FTY repl by ESC_CHI */
4852           /* 18 PI  repl by ESC_LAW */
4853          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4854      word multi_fac_id[] = {1, FTY};
4855      word multi_pi_id[]  = {1, PI};
4856      word multi_CiPN_id[]  = {1, OAD};
4857      word multi_ssext_id[]  = {1, ESC_SSEXT};
4858
4859      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4860
4861   byte   * cau;
4862   word ncci;
4863     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4864     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4865     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4866     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4867   byte force_mt_info = false;
4868   byte dir;
4869   dword d;
4870   word w;
4871
4872   a = plci->adapter;
4873   Id = ((word)plci->Id<<8)|a->Id;
4874   PUT_WORD(&SS_Ind[4],0x0000);
4875
4876   if (plci->sig_remove_id)
4877   {
4878     plci->Sig.RNR = 2; /* discard */
4879     dbug(1,dprintf("SIG discard while remove pending"));
4880     return;
4881   }
4882   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4883   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4884     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4885   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4886   {
4887     plci->Sig.RNR = 1;
4888     return;
4889   }
4890   if(plci->Sig.Ind==HANGUP && plci->channels)
4891   {
4892     plci->Sig.RNR = 1;
4893     plci->hangup_flow_ctrl_timer++;
4894     /* recover the network layer after timeout */
4895     if(plci->hangup_flow_ctrl_timer==100)
4896     {
4897       dbug(1,dprintf("Exceptional disc"));
4898       plci->Sig.RNR = 0;
4899       plci->hangup_flow_ctrl_timer = 0;
4900       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4901       {
4902         if (a->ncci_plci[ncci] == plci->Id)
4903         {
4904           cleanup_ncci_data (plci, ncci);
4905           if(plci->channels)plci->channels--;
4906           if (plci->appl)
4907             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4908         }
4909       }
4910       if (plci->appl)
4911         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4912       plci_remove(plci);
4913       plci->State=IDLE;
4914     }
4915     return;
4916   }
4917
4918   /* do first parse the info with no OAD in, because OAD will be converted */
4919   /* first the multiple facility IE, then mult. progress ind.              */
4920   /* then the parameters for the info_ind + conn_ind                       */
4921   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4922   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4923   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4924
4925   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4926
4927   IndParse(plci,parms_id,parms,0);
4928   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4929   esc_chi  = parms[14];
4930   esc_law  = parms[18];
4931   pty_cai  = parms[24];
4932   esc_cr   = parms[25];
4933   esc_profile = parms[27];
4934   if(esc_cr[0] && plci)
4935   {
4936     if(plci->cr_enquiry && plci->appl)
4937     {
4938       plci->cr_enquiry = false;
4939       /* d = MANU_ID            */
4940       /* w = m_command          */
4941       /* b = total length       */
4942       /* b = indication type    */
4943       /* b = length of all IEs  */
4944       /* b = IE1                */
4945       /* S = IE1 length + cont. */
4946       /* b = IE2                */
4947       /* S = IE2 length + cont. */
4948       sendf(plci->appl,
4949         _MANUFACTURER_I,
4950         Id,
4951         0,
4952         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4953         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);
4954     }
4955   }
4956   /* create the additional info structure                                  */
4957   add_i[1] = parms[15]; /* KEY of additional info */
4958   add_i[2] = parms[11]; /* UUI of additional info */
4959   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4960
4961   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4962   /* indication returns by the card if requested by the function           */
4963   /* AutomaticLaw() after driver init                                      */
4964   if (a->automatic_law<4)
4965   {
4966     if(esc_law[0]){
4967       if(esc_law[2]){
4968         dbug(0,dprintf("u-Law selected"));
4969         a->u_law = 1;
4970       }
4971       else {
4972         dbug(0,dprintf("a-Law selected"));
4973         a->u_law = 0;
4974       }
4975       a->automatic_law = 4;
4976       if(plci==a->automatic_lawPLCI) {
4977         plci->internal_command = 0;
4978         sig_req(plci,REMOVE,0);
4979         send_req(plci);
4980         a->automatic_lawPLCI = NULL;
4981       }
4982     }
4983     if (esc_profile[0])
4984     {
4985       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4986         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4987         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4988         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4989
4990       a->profile.Global_Options &= 0x000000ffL;
4991       a->profile.B1_Protocols &= 0x000003ffL;
4992       a->profile.B2_Protocols &= 0x00001fdfL;
4993       a->profile.B3_Protocols &= 0x000000b7L;
4994
4995       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4996         GL_BCHANNEL_OPERATION_SUPPORTED;
4997       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4998       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4999       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5000       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5001       a->man_profile.private_options = 0;
5002
5003       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5004       {
5005         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5006         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5007       }
5008
5009
5010       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5011         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5012       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5013       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5014
5015
5016       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5017         a->man_profile.private_options |= 1L << PRIVATE_T38;
5018
5019
5020       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5021         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5022
5023
5024       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5025         a->man_profile.private_options |= 1L << PRIVATE_V18;
5026
5027
5028       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5029         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5030
5031
5032       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5033         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5034
5035
5036       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5037         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5038
5039
5040       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5041         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5042
5043
5044       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5045         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5046
5047     }
5048     else
5049     {
5050       a->profile.Global_Options &= 0x0000007fL;
5051       a->profile.B1_Protocols &= 0x000003dfL;
5052       a->profile.B2_Protocols &= 0x00001adfL;
5053       a->profile.B3_Protocols &= 0x000000b7L;
5054       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5055     }
5056     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5057       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5058     {
5059       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5060     }
5061     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5062     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5063       UnMapController (a->Id), a->profile.Global_Options,
5064       a->profile.B1_Protocols, a->profile.B2_Protocols,
5065       a->profile.B3_Protocols, a->manufacturer_features));
5066   }
5067   /* codec plci for the handset/hook state support is just an internal id  */
5068   if(plci!=a->AdvCodecPLCI)
5069   {
5070     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5071     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5072     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5073     SendInfo(plci,Id, parms, force_mt_info);
5074
5075     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5076
5077   }
5078
5079   /* switch the codec to the b-channel                                     */
5080   if(esc_chi[0] && plci && !plci->SuppState){
5081     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5082     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5083     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5084     if(plci->tel==ADV_VOICE && plci->appl) {
5085       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5086     }
5087   }
5088
5089   if(plci->appl) Number = plci->appl->Number++;
5090
5091   switch(plci->Sig.Ind) {
5092   /* Response to Get_Supported_Services request */
5093   case S_SUPPORTED:
5094     dbug(1,dprintf("S_Supported"));
5095     if(!plci->appl) break;
5096     if(pty_cai[0]==4)
5097     {
5098       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5099     }
5100     else
5101     {
5102       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5103     }
5104     PUT_WORD (&CF_Ind[1], 0);
5105     PUT_WORD (&CF_Ind[4], 0);
5106     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5107     plci_remove(plci);
5108     break;
5109                     
5110   /* Supplementary Service rejected */
5111   case S_SERVICE_REJ:
5112     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5113     if(!pty_cai[0]) break;
5114     switch (pty_cai[5])
5115     {
5116     case ECT_EXECUTE:
5117     case THREE_PTY_END:
5118     case THREE_PTY_BEGIN:
5119       if(!plci->relatedPTYPLCI) break;
5120       tplci = plci->relatedPTYPLCI;
5121       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5122       if(tplci->tel) rId|=EXT_CONTROLLER;
5123       if(pty_cai[5]==ECT_EXECUTE)
5124       {
5125         PUT_WORD(&SS_Ind[1],S_ECT);
5126
5127         plci->vswitchstate=0;
5128         plci->relatedPTYPLCI->vswitchstate=0;
5129
5130       }
5131       else
5132       {
5133         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5134       }
5135       if(pty_cai[2]!=0xff)
5136       {
5137         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5138       }
5139       else
5140       {
5141         PUT_WORD(&SS_Ind[4],0x300E);
5142       }
5143       plci->relatedPTYPLCI = NULL;
5144       plci->ptyState = 0;
5145       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5146       break;
5147
5148     case CALL_DEFLECTION:
5149       if(pty_cai[2]!=0xff)
5150       {
5151         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5152       }
5153       else
5154       {
5155         PUT_WORD(&SS_Ind[4],0x300E);
5156       }
5157       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5158       for(i=0; i<max_appl; i++)
5159       {
5160         if(application[i].CDEnable)
5161         {
5162           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5163           application[i].CDEnable = false;
5164         }
5165       }
5166       break;
5167
5168     case DEACTIVATION_DIVERSION:
5169     case ACTIVATION_DIVERSION:
5170     case DIVERSION_INTERROGATE_CFU:
5171     case DIVERSION_INTERROGATE_CFB:
5172     case DIVERSION_INTERROGATE_CFNR:
5173     case DIVERSION_INTERROGATE_NUM:
5174     case CCBS_REQUEST:
5175     case CCBS_DEACTIVATE:
5176     case CCBS_INTERROGATE:
5177       if(!plci->appl) break;
5178       if(pty_cai[2]!=0xff)
5179       {
5180         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5181       }
5182       else
5183       {
5184         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5185       }
5186       switch (pty_cai[5])
5187       {
5188         case DEACTIVATION_DIVERSION:
5189           dbug(1,dprintf("Deact_Div"));
5190           Interr_Err_Ind[0]=0x9;
5191           Interr_Err_Ind[3]=0x6;
5192           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5193           break;
5194         case ACTIVATION_DIVERSION:
5195           dbug(1,dprintf("Act_Div"));
5196           Interr_Err_Ind[0]=0x9;
5197           Interr_Err_Ind[3]=0x6;
5198           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5199           break;
5200         case DIVERSION_INTERROGATE_CFU:
5201         case DIVERSION_INTERROGATE_CFB:
5202         case DIVERSION_INTERROGATE_CFNR:
5203           dbug(1,dprintf("Interr_Div"));
5204           Interr_Err_Ind[0]=0xa;
5205           Interr_Err_Ind[3]=0x7;
5206           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5207           break;
5208         case DIVERSION_INTERROGATE_NUM:
5209           dbug(1,dprintf("Interr_Num"));
5210           Interr_Err_Ind[0]=0xa;
5211           Interr_Err_Ind[3]=0x7;
5212           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5213           break;
5214         case CCBS_REQUEST:
5215           dbug(1,dprintf("CCBS Request"));
5216           Interr_Err_Ind[0]=0xd;
5217           Interr_Err_Ind[3]=0xa;
5218           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5219           break;
5220         case CCBS_DEACTIVATE:
5221           dbug(1,dprintf("CCBS Deactivate"));
5222           Interr_Err_Ind[0]=0x9;
5223           Interr_Err_Ind[3]=0x6;
5224           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5225           break;
5226         case CCBS_INTERROGATE:
5227           dbug(1,dprintf("CCBS Interrogate"));
5228           Interr_Err_Ind[0]=0xb;
5229           Interr_Err_Ind[3]=0x8;
5230           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5231           break;
5232       }
5233       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5234       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5235       plci_remove(plci);
5236       break;
5237     case ACTIVATION_MWI:      
5238     case DEACTIVATION_MWI:
5239       if(pty_cai[5]==ACTIVATION_MWI)
5240       {
5241         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5242       }
5243       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5244       
5245       if(pty_cai[2]!=0xff)
5246       {
5247         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5248       }
5249       else
5250       {
5251         PUT_WORD(&SS_Ind[4],0x300E);
5252       }
5253
5254       if(plci->cr_enquiry)
5255       {
5256         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5257         plci_remove(plci);
5258       }
5259       else
5260       {
5261         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5262       }
5263       break;
5264     case CONF_ADD: /* ERROR */
5265     case CONF_BEGIN:
5266     case CONF_DROP:
5267     case CONF_ISOLATE:
5268     case CONF_REATTACH:
5269       CONF_Ind[0]=9;
5270       CONF_Ind[3]=6;   
5271       switch(pty_cai[5])
5272       {
5273       case CONF_BEGIN:
5274           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5275           plci->ptyState = 0;
5276           break;
5277       case CONF_DROP:
5278           CONF_Ind[0]=5;
5279           CONF_Ind[3]=2;
5280           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5281           plci->ptyState = CONNECTED;
5282           break;
5283       case CONF_ISOLATE:
5284           CONF_Ind[0]=5;
5285           CONF_Ind[3]=2;
5286           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5287           plci->ptyState = CONNECTED;
5288           break;
5289       case CONF_REATTACH:
5290           CONF_Ind[0]=5;
5291           CONF_Ind[3]=2;
5292           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5293           plci->ptyState = CONNECTED;
5294           break;
5295       case CONF_ADD:
5296           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5297           plci->relatedPTYPLCI = NULL;
5298           tplci=plci->relatedPTYPLCI;
5299           if(tplci) tplci->ptyState = CONNECTED;
5300           plci->ptyState = CONNECTED;
5301           break;
5302       }
5303           
5304       if(pty_cai[2]!=0xff)
5305       {
5306         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5307       }
5308       else
5309       {
5310         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5311                                             within the required time */
5312       }
5313
5314       PUT_DWORD(&CONF_Ind[6],0x0);
5315       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5316       break;
5317     }
5318     break;
5319
5320   /* Supplementary Service indicates success */
5321   case S_SERVICE:
5322     dbug(1,dprintf("Service_Ind"));
5323     PUT_WORD (&CF_Ind[4], 0);
5324     switch (pty_cai[5])
5325     {
5326     case THREE_PTY_END:
5327     case THREE_PTY_BEGIN:
5328     case ECT_EXECUTE:
5329       if(!plci->relatedPTYPLCI) break;
5330       tplci = plci->relatedPTYPLCI;
5331       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5332       if(tplci->tel) rId|=EXT_CONTROLLER;
5333       if(pty_cai[5]==ECT_EXECUTE)
5334       {
5335         PUT_WORD(&SS_Ind[1],S_ECT);
5336
5337         if(plci->vswitchstate!=3)
5338         {
5339
5340         plci->ptyState = IDLE;
5341         plci->relatedPTYPLCI = NULL;
5342         plci->ptyState = 0;
5343
5344         }
5345
5346         dbug(1,dprintf("ECT OK"));
5347         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5348
5349
5350
5351       }
5352       else
5353       {
5354         switch (plci->ptyState)
5355         {
5356         case S_3PTY_BEGIN:
5357           plci->ptyState = CONNECTED;
5358           dbug(1,dprintf("3PTY ON"));
5359           break;
5360
5361         case S_3PTY_END:
5362           plci->ptyState = IDLE;
5363           plci->relatedPTYPLCI = NULL;
5364           plci->ptyState = 0;
5365           dbug(1,dprintf("3PTY OFF"));
5366           break;
5367         }
5368         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5369         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5370       }
5371       break;
5372
5373     case CALL_DEFLECTION:
5374       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5375       for(i=0; i<max_appl; i++)
5376       {
5377         if(application[i].CDEnable)
5378         {
5379           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5380           application[i].CDEnable = false;
5381         }
5382       }
5383       break;
5384
5385     case DEACTIVATION_DIVERSION:
5386     case ACTIVATION_DIVERSION:
5387       if(!plci->appl) break;
5388       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5389       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5390       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5391       plci_remove(plci);
5392       break;
5393
5394     case DIVERSION_INTERROGATE_CFU:
5395     case DIVERSION_INTERROGATE_CFB:
5396     case DIVERSION_INTERROGATE_CFNR:
5397     case DIVERSION_INTERROGATE_NUM:
5398     case CCBS_REQUEST:
5399     case CCBS_DEACTIVATE:
5400     case CCBS_INTERROGATE:
5401       if(!plci->appl) break;
5402       switch (pty_cai[5])
5403       {
5404         case DIVERSION_INTERROGATE_CFU:
5405         case DIVERSION_INTERROGATE_CFB:
5406         case DIVERSION_INTERROGATE_CFNR:
5407           dbug(1,dprintf("Interr_Div"));
5408           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5409           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5410           break;
5411         case DIVERSION_INTERROGATE_NUM:
5412           dbug(1,dprintf("Interr_Num"));
5413           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5414           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5415           break;
5416         case CCBS_REQUEST:
5417           dbug(1,dprintf("CCBS Request"));
5418           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5419           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5420           break;
5421         case CCBS_DEACTIVATE:
5422           dbug(1,dprintf("CCBS Deactivate"));
5423           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5424           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5425           break;
5426         case CCBS_INTERROGATE:
5427           dbug(1,dprintf("CCBS Interrogate"));
5428           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5429           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430           break;
5431       }
5432       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5433       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5434       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5435       plci_remove(plci);
5436       break;
5437
5438     case ACTIVATION_MWI:
5439     case DEACTIVATION_MWI:
5440       if(pty_cai[5]==ACTIVATION_MWI)
5441       {
5442         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5443       }
5444       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5445       if(plci->cr_enquiry)
5446       {
5447         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5448         plci_remove(plci);
5449       }
5450       else
5451       {
5452         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5453       }
5454       break;
5455     case MWI_INDICATION:
5456       if(pty_cai[0]>=0x12)
5457       {
5458         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5459         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5460         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5461         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5462         {
5463           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5464           {
5465             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5466             plci_remove(plci);
5467             return;
5468           }
5469           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5470           pty_cai[0]=0;
5471         }
5472         else
5473         {
5474           for(i=0; i<max_appl; i++)
5475           {                     
5476             if(a->Notification_Mask[i]&SMASK_MWI)
5477             {
5478               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5479               pty_cai[0]=0;
5480             }
5481           }
5482         }
5483
5484         if(!pty_cai[0])
5485         { /* acknowledge */
5486           facility[2]= 0; /* returncode */
5487         }
5488         else facility[2]= 0xff;
5489       }
5490       else
5491       {
5492         /* reject */
5493         facility[2]= 0xff; /* returncode */
5494       }
5495       facility[0]= 2;
5496       facility[1]= MWI_RESPONSE; /* Function */
5497       add_p(plci,CAI,facility);
5498       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5499       sig_req(plci,S_SERVICE,0);
5500       send_req(plci);
5501       plci->command = 0;
5502       next_internal_command (Id, plci);
5503       break;
5504     case CONF_ADD: /* OK */
5505     case CONF_BEGIN:
5506     case CONF_DROP:
5507     case CONF_ISOLATE:
5508     case CONF_REATTACH:
5509     case CONF_PARTYDISC:
5510       CONF_Ind[0]=9;
5511       CONF_Ind[3]=6;
5512       switch(pty_cai[5])
5513       {
5514       case CONF_BEGIN:
5515           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5516           if(pty_cai[0]==6)
5517           {
5518               d=pty_cai[6];
5519               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5520           }
5521           else
5522           {
5523               PUT_DWORD(&CONF_Ind[6],0x0);
5524           }
5525           break;
5526       case CONF_ISOLATE:
5527           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5528           CONF_Ind[0]=5;
5529           CONF_Ind[3]=2;
5530           break;
5531       case CONF_REATTACH:
5532           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5533           CONF_Ind[0]=5;
5534           CONF_Ind[3]=2;
5535           break;
5536       case CONF_DROP:
5537           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5538           CONF_Ind[0]=5;
5539           CONF_Ind[3]=2;
5540           break;
5541       case CONF_ADD:
5542           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5543           d=pty_cai[6];
5544           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5545           tplci=plci->relatedPTYPLCI;
5546           if(tplci) tplci->ptyState = CONNECTED;
5547           break;
5548       case CONF_PARTYDISC:
5549           CONF_Ind[0]=7;
5550           CONF_Ind[3]=4;          
5551           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5552           d=pty_cai[6];
5553           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5554           break;
5555       }
5556       plci->ptyState = CONNECTED;
5557       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5558       break;
5559     case CCBS_INFO_RETAIN:
5560     case CCBS_ERASECALLLINKAGEID:
5561     case CCBS_STOP_ALERTING:
5562       CONF_Ind[0]=5;
5563       CONF_Ind[3]=2;
5564       switch(pty_cai[5])
5565       {
5566       case CCBS_INFO_RETAIN:
5567         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5568         break;
5569       case CCBS_STOP_ALERTING:
5570         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5571     break;
5572       case CCBS_ERASECALLLINKAGEID:
5573         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5574         CONF_Ind[0]=7;
5575         CONF_Ind[3]=4;
5576         CONF_Ind[6]=0;
5577         CONF_Ind[7]=0;
5578         break;
5579       }      
5580       w=pty_cai[6];
5581       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5582
5583       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5584       {
5585         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5586       }
5587       else
5588       {
5589         for(i=0; i<max_appl; i++)
5590             if(a->Notification_Mask[i]&SMASK_CCBS)
5591                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5592       }
5593       break;
5594     }
5595     break;
5596   case CALL_HOLD_REJ:
5597     cau = parms[7];
5598     if(cau)
5599     {
5600       i = _L3_CAUSE | cau[2];
5601       if(cau[2]==0) i = 0x3603;
5602     }
5603     else
5604     {
5605       i = 0x3603;
5606     }
5607     PUT_WORD(&SS_Ind[1],S_HOLD);
5608     PUT_WORD(&SS_Ind[4],i);
5609     if(plci->SuppState == HOLD_REQUEST)
5610     {
5611       plci->SuppState = IDLE;
5612       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5613     }
5614     break;
5615
5616   case CALL_HOLD_ACK:
5617     if(plci->SuppState == HOLD_REQUEST)
5618     {
5619       plci->SuppState = CALL_HELD;
5620       CodecIdCheck(a, plci);
5621       start_internal_command (Id, plci, hold_save_command);
5622     }
5623     break;
5624
5625   case CALL_RETRIEVE_REJ:
5626     cau = parms[7];
5627     if(cau)
5628     {
5629       i = _L3_CAUSE | cau[2];
5630       if(cau[2]==0) i = 0x3603;
5631     }
5632     else
5633     {
5634       i = 0x3603;
5635     }
5636     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5637     PUT_WORD(&SS_Ind[4],i);
5638     if(plci->SuppState == RETRIEVE_REQUEST)
5639     {
5640       plci->SuppState = CALL_HELD;
5641       CodecIdCheck(a, plci);
5642       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5643     }
5644     break;
5645
5646   case CALL_RETRIEVE_ACK:
5647     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5648     if(plci->SuppState == RETRIEVE_REQUEST)
5649     {
5650       plci->SuppState = IDLE;
5651       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5652       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5653       if(plci->tel)
5654       {
5655         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5656         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5657         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5658         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5659         {
5660           dbug(1,dprintf("Get B-ch"));
5661           start_internal_command (Id, plci, retrieve_restore_command);
5662         }
5663         else
5664           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5665       }
5666       else
5667         start_internal_command (Id, plci, retrieve_restore_command);
5668     }
5669     break;
5670
5671   case INDICATE_IND:
5672     if(plci->State != LISTENING) {
5673       sig_req(plci,HANGUP,0);
5674       send_req(plci);
5675       break;
5676     }
5677     cip = find_cip(a,parms[4],parms[6]);
5678     cip_mask = 1L<<cip;
5679     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5680     clear_c_ind_mask (plci);
5681     if (!remove_started && !a->adapter_disabled)
5682     {
5683       set_c_ind_mask_bit (plci, MAX_APPL);
5684       group_optimization(a, plci);
5685       for(i=0; i<max_appl; i++) {
5686         if(application[i].Id
5687         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5688         && CPN_filter_ok(parms[0],a,i)
5689         && test_group_ind_mask_bit (plci, i) ) {
5690           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5691           set_c_ind_mask_bit (plci, i);
5692           dump_c_ind_mask (plci);
5693           plci->State = INC_CON_PENDING;
5694           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5695             CALL_DIR_IN | CALL_DIR_ANSWER;
5696           if(esc_chi[0]) {
5697             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5698             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5699           }
5700           /* if a listen on the ext controller is done, check if hook states */
5701           /* are supported or if just a on board codec must be activated     */
5702           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5703             if(a->profile.Global_Options & HANDSET)
5704               plci->tel = ADV_VOICE;
5705             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5706               plci->tel = CODEC;
5707             if(plci->tel) Id|=EXT_CONTROLLER;
5708             a->codec_listen[i] = plci;
5709           }
5710
5711           sendf(&application[i],_CONNECT_I,Id,0,
5712                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5713                              parms[0],    /* CalledPartyNumber   */
5714                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5715                              parms[2],    /* CalledPartySubad    */
5716                              parms[3],    /* CallingPartySubad   */
5717                              parms[4],    /* BearerCapability    */
5718                              parms[5],    /* LowLC               */
5719                              parms[6],    /* HighLC              */
5720                              ai_len,      /* nested struct add_i */
5721                              add_i[0],    /* B channel info    */
5722                              add_i[1],    /* keypad facility   */
5723                              add_i[2],    /* user user data    */
5724                              add_i[3],    /* nested facility   */
5725                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5726                              );
5727           SendSSExtInd(&application[i],
5728                         plci,
5729                         Id,
5730                         multi_ssext_parms);
5731           SendSetupInfo(&application[i],
5732                         plci,
5733                         Id,
5734                         parms,
5735                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5736         }
5737       }
5738       clear_c_ind_mask_bit (plci, MAX_APPL);
5739       dump_c_ind_mask (plci);
5740     }
5741     if(c_ind_mask_empty (plci)) {
5742       sig_req(plci,HANGUP,0);
5743       send_req(plci);
5744       plci->State = IDLE;
5745     }
5746     plci->notifiedcall = 0;
5747     a->listen_active--;
5748     listen_check(a);
5749     break;
5750
5751   case CALL_PEND_NOTIFY:
5752     plci->notifiedcall = 1;
5753     listen_check(a);
5754     break;
5755
5756   case CALL_IND:
5757   case CALL_CON:
5758     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5759     {
5760       if(plci->internal_command==PERM_COD_CONN_PEND)
5761       {
5762         if(plci->State==ADVANCED_VOICE_NOSIG)
5763         {
5764           dbug(1,dprintf("***Codec OK"));
5765           if(a->AdvSignalPLCI)
5766           {
5767             tplci = a->AdvSignalPLCI;
5768             if(tplci->spoofed_msg)
5769             {
5770               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5771               tplci->command = 0;
5772               tplci->internal_command = 0;
5773               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5774               switch (tplci->spoofed_msg)
5775               {
5776               case CALL_RES:
5777                 tplci->command = _CONNECT_I|RESPONSE;
5778                 api_load_msg (&tplci->saved_msg, saved_parms);
5779                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5780                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5781                 {
5782                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5783                   add_p(tplci,LLI,"\x01\x01");
5784                 }
5785                 add_s(tplci, CONN_NR, &saved_parms[2]);
5786                 add_s(tplci, LLC, &saved_parms[4]);
5787                 add_ai(tplci, &saved_parms[5]);
5788                 tplci->State = INC_CON_ACCEPT;
5789                 sig_req(tplci, CALL_RES,0);
5790                 send_req(tplci);
5791                 break;
5792
5793               case AWAITING_SELECT_B:
5794                 dbug(1,dprintf("Select_B continue"));
5795                 start_internal_command (x_Id, tplci, select_b_command);
5796                 break;
5797
5798               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5799                 if(!tplci->Sig.Id)
5800                 {
5801                   dbug(1,dprintf("No SigID!"));
5802                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5803                   plci_remove(tplci);
5804                   break;
5805                 }
5806                 tplci->command = _MANUFACTURER_R;
5807                 api_load_msg (&tplci->saved_msg, saved_parms);
5808                 dir = saved_parms[2].info[0];
5809                 if(dir==1) {
5810                   sig_req(tplci,CALL_REQ,0);
5811                 }
5812                 else if(!dir){
5813                   sig_req(tplci,LISTEN_REQ,0);
5814                 }
5815                 send_req(tplci);
5816                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5817                 break;
5818
5819               case (CALL_REQ|AWAITING_MANUF_CON):
5820                 sig_req(tplci,CALL_REQ,0);
5821                 send_req(tplci);
5822                 break;
5823
5824               case CALL_REQ:
5825                 if(!tplci->Sig.Id)
5826                 {
5827                   dbug(1,dprintf("No SigID!"));
5828                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5829                   plci_remove(tplci);
5830                   break;
5831                 }
5832                 tplci->command = _CONNECT_R;
5833                 api_load_msg (&tplci->saved_msg, saved_parms);
5834                 add_s(tplci,CPN,&saved_parms[1]);
5835                 add_s(tplci,DSA,&saved_parms[3]);
5836                 add_ai(tplci,&saved_parms[9]);
5837                 sig_req(tplci,CALL_REQ,0);
5838                 send_req(tplci);
5839                 break;
5840
5841               case CALL_RETRIEVE:
5842                 tplci->command = C_RETRIEVE_REQ;
5843                 sig_req(tplci,CALL_RETRIEVE,0);
5844                 send_req(tplci);
5845                 break;
5846               }
5847               tplci->spoofed_msg = 0;
5848               if (tplci->internal_command == 0)
5849                 next_internal_command (x_Id, tplci);
5850             }
5851           }
5852           next_internal_command (Id, plci);
5853           break;
5854         }
5855         dbug(1,dprintf("***Codec Hook Init Req"));
5856         plci->internal_command = PERM_COD_HOOK;
5857         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5858         sig_req(plci,TEL_CTRL,0);
5859         send_req(plci);
5860       }
5861     }
5862     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5863     && plci->State!=INC_ACT_PENDING)
5864     {
5865       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5866       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5867       {
5868         chi[2] = plci->b_channel;
5869         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5870       }
5871       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5872       plci->State = INC_ACT_PENDING;
5873     }
5874     break;
5875
5876   case TEL_CTRL:
5877     Number = 0;
5878     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5879     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5880       switch (ie[1]&0x91) {
5881         case 0x80:   /* hook off */
5882         case 0x81:
5883           if(plci->internal_command==PERM_COD_HOOK)
5884           {
5885             dbug(1,dprintf("init:hook_off"));
5886             plci->hook_state = ie[1];
5887             next_internal_command (Id, plci);
5888             break;
5889           }
5890           else /* ignore doubled hook indications */
5891           {
5892             if( ((plci->hook_state)&0xf0)==0x80)
5893             {
5894               dbug(1,dprintf("ignore hook"));
5895               break;
5896             }
5897             plci->hook_state = ie[1]&0x91;
5898           }
5899           /* check for incoming call pending */
5900           /* and signal '+'.Appl must decide */
5901           /* with connect_res if call must   */
5902           /* accepted or not                 */
5903           for(i=0, tplci=NULL;i<max_appl;i++){
5904             if(a->codec_listen[i]
5905             && (a->codec_listen[i]->State==INC_CON_PENDING
5906               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5907               tplci = a->codec_listen[i];
5908               tplci->appl = &application[i];
5909             }
5910           }
5911           /* no incoming call, do outgoing call */
5912           /* and signal '+' if outg. setup   */
5913           if(!a->AdvSignalPLCI && !tplci){
5914             if((i=get_plci(a))) {
5915               a->AdvSignalPLCI = &a->plci[i-1];
5916               tplci = a->AdvSignalPLCI;
5917               tplci->tel  = ADV_VOICE;
5918               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5919               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5920                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5921                 add_p(tplci,LLI,"\x01\x01");
5922               }
5923               add_p(tplci, CAI, voice_cai);
5924               add_p(tplci, OAD, a->TelOAD);
5925               add_p(tplci, OSA, a->TelOSA);
5926               add_p(tplci,SHIFT|6,NULL);
5927               add_p(tplci,SIN,"\x02\x01\x00");
5928               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5929               sig_req(tplci,ASSIGN,DSIG_ID);
5930               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5931               a->AdvSignalPLCI->command = 0;
5932               tplci->appl = a->AdvSignalAppl;
5933               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5934               send_req(tplci);
5935             }
5936
5937           }
5938
5939           if(!tplci) break;
5940           Id = ((word)tplci->Id<<8)|a->Id;
5941           Id|=EXT_CONTROLLER;
5942           sendf(tplci->appl,
5943                 _FACILITY_I,
5944                 Id,
5945                 0,
5946                 "ws", (word)0, "\x01+");
5947           break;
5948
5949         case 0x90:   /* hook on  */
5950         case 0x91:
5951           if(plci->internal_command==PERM_COD_HOOK)
5952           {
5953             dbug(1,dprintf("init:hook_on"));
5954             plci->hook_state = ie[1]&0x91;
5955             next_internal_command (Id, plci);
5956             break;
5957           }
5958           else /* ignore doubled hook indications */
5959           {
5960             if( ((plci->hook_state)&0xf0)==0x90) break;
5961             plci->hook_state = ie[1]&0x91;
5962           }
5963           /* hangup the adv. voice call and signal '-' to the appl */
5964           if(a->AdvSignalPLCI) {
5965             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5966             if(plci->tel) Id|=EXT_CONTROLLER;
5967             sendf(a->AdvSignalAppl,
5968                   _FACILITY_I,
5969                   Id,
5970                   0,
5971                   "ws", (word)0, "\x01-");
5972             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5973             a->AdvSignalPLCI->command = 0;
5974             sig_req(a->AdvSignalPLCI,HANGUP,0);
5975             send_req(a->AdvSignalPLCI);
5976           }
5977           break;
5978       }
5979     }
5980     break;
5981
5982   case RESUME:
5983     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5984     PUT_WORD(&resume_cau[4],GOOD);
5985     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5986     break;
5987
5988   case SUSPEND:
5989     clear_c_ind_mask (plci);
5990
5991     if (plci->NL.Id && !plci->nl_remove_id) {
5992       mixer_remove (plci);
5993       nl_req_ncci(plci,REMOVE,0);
5994     }
5995     if (!plci->sig_remove_id) {
5996       plci->internal_command = 0;
5997       sig_req(plci,REMOVE,0);
5998     }
5999     send_req(plci);
6000     if(!plci->channels) {
6001       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6002       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6003     }
6004     break;
6005
6006   case SUSPEND_REJ:
6007     break;
6008
6009   case HANGUP:
6010     plci->hangup_flow_ctrl_timer=0;
6011     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6012     cau = parms[7];
6013     if(cau) {
6014       i = _L3_CAUSE | cau[2];
6015       if(cau[2]==0) i = 0;
6016       else if(cau[2]==8) i = _L1_ERROR;
6017       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6018       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6019     }
6020     else {
6021       i = _L3_ERROR;
6022     }
6023
6024     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6025     {
6026       for(i=0; i<max_appl; i++)
6027       {
6028         if(test_c_ind_mask_bit (plci, i))
6029           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6030       }
6031     }
6032     else
6033     {
6034       clear_c_ind_mask (plci);
6035     }
6036     if(!plci->appl)
6037     {
6038       if (plci->State == LISTENING)
6039       {
6040         plci->notifiedcall=0;
6041         a->listen_active--;
6042       }
6043       plci->State = INC_DIS_PENDING;
6044       if(c_ind_mask_empty (plci))
6045       {
6046         plci->State = IDLE;
6047         if (plci->NL.Id && !plci->nl_remove_id)
6048         {
6049           mixer_remove (plci);
6050           nl_req_ncci(plci,REMOVE,0);
6051         }
6052         if (!plci->sig_remove_id)
6053         {
6054           plci->internal_command = 0;
6055           sig_req(plci,REMOVE,0);
6056         }
6057         send_req(plci);
6058       }
6059     }
6060     else
6061     {
6062         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6063         /* result in a second HANGUP! Don't generate another        */
6064         /* DISCONNECT                                               */
6065       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6066       {
6067         if(plci->State==RESUMING)
6068         {
6069           PUT_WORD(&resume_cau[4],i);
6070           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6071         }
6072         plci->State = INC_DIS_PENDING;
6073         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6074       }
6075     }
6076     break;
6077
6078   case SSEXT_IND:
6079     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6080     break;
6081
6082   case VSWITCH_REQ:
6083     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6084     break;
6085   case VSWITCH_IND:
6086  if(plci->relatedPTYPLCI &&
6087   plci->vswitchstate==3 &&
6088   plci->relatedPTYPLCI->vswitchstate==3 &&
6089   parms[MAXPARMSIDS-1][0])
6090  {
6091   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6092   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6093   send_req(plci->relatedPTYPLCI);
6094  }
6095     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6096     break;
6097
6098   }
6099 }
6100
6101
6102 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6103 {
6104   word i;
6105   byte   * ie;
6106   word Info_Number;
6107   byte   * Info_Element;
6108   word Info_Mask = 0;
6109
6110   dbug(1,dprintf("SetupInfo"));
6111
6112   for(i=0; i<MAXPARMSIDS; i++) {
6113     ie = parms[i];
6114     Info_Number = 0;
6115     Info_Element = ie;
6116     if(ie[0]) {
6117       switch(i) {
6118       case 0:
6119         dbug(1,dprintf("CPN "));
6120         Info_Number = 0x0070;
6121         Info_Mask   = 0x80;
6122         Info_Sent_Flag = true;
6123         break;
6124       case 8:  /* display      */
6125         dbug(1,dprintf("display(%d)",i));
6126         Info_Number = 0x0028;
6127         Info_Mask = 0x04;
6128         Info_Sent_Flag = true;
6129         break;
6130       case 16: /* Channel Id */
6131         dbug(1,dprintf("CHI"));
6132         Info_Number = 0x0018;
6133         Info_Mask = 0x100;
6134         Info_Sent_Flag = true;
6135         mixer_set_bchannel_id (plci, Info_Element);
6136         break;
6137       case 19: /* Redirected Number */
6138         dbug(1,dprintf("RDN"));
6139         Info_Number = 0x0074;
6140         Info_Mask = 0x400;
6141         Info_Sent_Flag = true;
6142         break;
6143       case 20: /* Redirected Number extended */
6144         dbug(1,dprintf("RDX"));
6145         Info_Number = 0x0073;
6146         Info_Mask = 0x400;
6147         Info_Sent_Flag = true;
6148         break;
6149       case 22: /* Redirecing Number  */
6150         dbug(1,dprintf("RIN"));
6151         Info_Number = 0x0076;
6152         Info_Mask = 0x400;
6153         Info_Sent_Flag = true;
6154         break;
6155       default:
6156         Info_Number = 0;
6157         break;
6158       }
6159     }
6160
6161     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6162       Info_Number = 0x8000 |5;
6163       Info_Mask = 0x10;
6164       Info_Element = "";
6165     }
6166
6167     if(Info_Sent_Flag && Info_Number){
6168       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6169         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6170       }
6171     }
6172   }
6173 }
6174
6175
6176 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6177 {
6178   word i;
6179   word j;
6180   word k;
6181   byte   * ie;
6182   word Info_Number;
6183   byte   * Info_Element;
6184   word Info_Mask = 0;
6185   static byte charges[5] = {4,0,0,0,0};
6186   static byte cause[] = {0x02,0x80,0x00};
6187   APPL   *appl;
6188
6189   dbug(1,dprintf("InfoParse "));
6190
6191   if(
6192         !plci->appl
6193         && !plci->State
6194         && plci->Sig.Ind!=NCR_FACILITY
6195       )
6196   {
6197     dbug(1,dprintf("NoParse "));
6198     return;
6199   }
6200   cause[2] = 0;
6201   for(i=0; i<MAXPARMSIDS; i++) {
6202     ie = parms[i];
6203     Info_Number = 0;
6204     Info_Element = ie;
6205     if(ie[0]) {
6206       switch(i) {
6207       case 0:
6208         dbug(1,dprintf("CPN "));
6209         Info_Number = 0x0070;
6210         Info_Mask   = 0x80;
6211         break;
6212       case 7: /* ESC_CAU */
6213         dbug(1,dprintf("cau(0x%x)",ie[2]));
6214         Info_Number = 0x0008;
6215         Info_Mask = 0x00;
6216         cause[2] = ie[2];
6217         Info_Element = NULL;
6218         break;
6219       case 8:  /* display      */
6220         dbug(1,dprintf("display(%d)",i));
6221         Info_Number = 0x0028;
6222         Info_Mask = 0x04;
6223         break;
6224       case 9:  /* Date display */
6225         dbug(1,dprintf("date(%d)",i));
6226         Info_Number = 0x0029;
6227         Info_Mask = 0x02;
6228         break;
6229       case 10: /* charges */
6230         for(j=0;j<4;j++) charges[1+j] = 0;
6231         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6232         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6233         Info_Number = 0x4000;
6234         Info_Mask = 0x40;
6235         Info_Element = charges;
6236         break;
6237       case 11: /* user user info */
6238         dbug(1,dprintf("uui"));
6239         Info_Number = 0x007E;
6240         Info_Mask = 0x08;
6241         break;
6242       case 12: /* congestion receiver ready */
6243         dbug(1,dprintf("clRDY"));
6244         Info_Number = 0x00B0;
6245         Info_Mask = 0x08;
6246         Info_Element = "";
6247         break;
6248       case 13: /* congestion receiver not ready */
6249         dbug(1,dprintf("clNRDY"));
6250         Info_Number = 0x00BF;
6251         Info_Mask = 0x08;
6252         Info_Element = "";
6253         break;
6254       case 15: /* Keypad Facility */
6255         dbug(1,dprintf("KEY"));
6256         Info_Number = 0x002C;
6257         Info_Mask = 0x20;
6258         break;
6259       case 16: /* Channel Id */
6260         dbug(1,dprintf("CHI"));
6261         Info_Number = 0x0018;
6262         Info_Mask = 0x100;
6263         mixer_set_bchannel_id (plci, Info_Element);
6264         break;
6265       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6266         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6267         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6268         Info_Number = 0x0008;
6269         Info_Mask = 0x01;
6270         if(cause[2] != ie[2]) Info_Element = cause;
6271         break;
6272       case 19: /* Redirected Number */
6273         dbug(1,dprintf("RDN"));
6274         Info_Number = 0x0074;
6275         Info_Mask = 0x400;
6276         break;
6277       case 22: /* Redirecing Number  */
6278         dbug(1,dprintf("RIN"));
6279         Info_Number = 0x0076;
6280         Info_Mask = 0x400;
6281         break;
6282       case 23: /* Notification Indicator  */
6283         dbug(1,dprintf("NI"));
6284         Info_Number = (word)NI;
6285         Info_Mask = 0x210;
6286         break;
6287       case 26: /* Call State  */
6288         dbug(1,dprintf("CST"));
6289         Info_Number = (word)CST;
6290         Info_Mask = 0x01; /* do with cause i.e. for now */
6291         break;
6292       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6293         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6294         Info_Number = 0x8000 |ie[3];
6295         if(iesent) Info_Mask = 0xffff;
6296         else  Info_Mask = 0x10;
6297         Info_Element = "";
6298         break;
6299       default:
6300         Info_Number  = 0;
6301         Info_Mask    = 0;
6302         Info_Element = "";
6303         break;
6304       }
6305     }
6306
6307     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6308     {
6309       for(j=0; j<max_appl; j++)
6310       {
6311         appl = &application[j];
6312         if(Info_Number
6313         && appl->Id
6314         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6315         {
6316           dbug(1,dprintf("NCR_Ind"));
6317           iesent=true;
6318           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6319         }
6320       }
6321     }
6322     else if(!plci->appl)
6323     { /* overlap receiving broadcast */
6324       if(Info_Number==CPN
6325       || Info_Number==KEY
6326       || Info_Number==NI
6327       || Info_Number==DSP
6328       || Info_Number==UUI )
6329       {
6330         for(j=0; j<max_appl; j++)
6331         {
6332           if(test_c_ind_mask_bit (plci, j))
6333           {
6334             dbug(1,dprintf("Ovl_Ind"));
6335             iesent=true;
6336             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6337           }
6338         }
6339       }
6340     }               /* all other signalling states */
6341     else if(Info_Number
6342     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6343     {
6344       dbug(1,dprintf("Std_Ind"));
6345       iesent=true;
6346       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6347     }
6348   }
6349 }
6350
6351
6352 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6353                         dword info_mask, byte setupParse)
6354 {
6355   word i;
6356   word j;
6357   byte   * ie;
6358   word Info_Number;
6359   byte   * Info_Element;
6360   APPL   *appl;
6361   word Info_Mask = 0;
6362   byte iesent=0;
6363
6364   if(
6365       !plci->appl
6366       && !plci->State
6367       && plci->Sig.Ind!=NCR_FACILITY
6368       && !setupParse
6369       )
6370   {
6371     dbug(1,dprintf("NoM-IEParse "));
6372     return 0;
6373   }
6374   dbug(1,dprintf("M-IEParse "));
6375
6376   for(i=0; i<MAX_MULTI_IE; i++)
6377   {
6378     ie = parms[i];
6379     Info_Number = 0;
6380     Info_Element = ie;
6381     if(ie[0])
6382     {
6383       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6384       Info_Number = (word)ie_type;
6385       Info_Mask = (word)info_mask;
6386     }
6387
6388     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6389     {
6390       for(j=0; j<max_appl; j++)
6391       {
6392         appl = &application[j];
6393         if(Info_Number
6394         && appl->Id
6395         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6396         {
6397           iesent = true;
6398           dbug(1,dprintf("Mlt_NCR_Ind"));
6399           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6400         }
6401       }
6402     }
6403     else if(!plci->appl && Info_Number)
6404     {                                        /* overlap receiving broadcast */
6405       for(j=0; j<max_appl; j++)
6406       {
6407         if(test_c_ind_mask_bit (plci, j))
6408         {
6409           iesent = true;
6410           dbug(1,dprintf("Mlt_Ovl_Ind"));
6411           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6412         }
6413       }
6414     }                                        /* all other signalling states */
6415     else if(Info_Number
6416     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6417     {
6418       iesent = true;
6419       dbug(1,dprintf("Mlt_Std_Ind"));
6420       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6421     }
6422   }
6423   return iesent;
6424 }
6425
6426 static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6427 {
6428   word i;
6429    /* Format of multi_ssext_parms[i][]:
6430    0 byte length
6431    1 byte SSEXTIE
6432    2 byte SSEXT_REQ/SSEXT_IND
6433    3 byte length
6434    4 word SSExtCommand
6435    6... Params
6436    */
6437   if(
6438    plci
6439    && plci->State
6440    && plci->Sig.Ind!=NCR_FACILITY
6441     )
6442  for(i=0;i<MAX_MULTI_IE;i++)
6443     {
6444       if(parms[i][0]<6) continue;
6445    if(parms[i][2]==SSEXT_REQ) continue;
6446
6447    if(appl)
6448    {
6449     parms[i][0]=0; /* kill it */
6450     sendf(appl,_MANUFACTURER_I,
6451     Id,
6452     0,
6453     "dwS",
6454     _DI_MANU_ID,
6455     _DI_SSEXT_CTRL,
6456     &parms[i][3]);
6457    }
6458    else if(plci->appl)
6459    {
6460     parms[i][0]=0; /* kill it */
6461     sendf(plci->appl,_MANUFACTURER_I,
6462     Id,
6463     0,
6464     "dwS",
6465     _DI_MANU_ID,
6466     _DI_SSEXT_CTRL,
6467     &parms[i][3]);
6468    }
6469     }
6470 };
6471
6472 static void nl_ind(PLCI *plci)
6473 {
6474   byte ch;
6475   word ncci;
6476   dword Id;
6477   DIVA_CAPI_ADAPTER   * a;
6478   word NCCIcode;
6479   APPL   * APPLptr;
6480   word count;
6481   word Num;
6482   word i, ncpi_state;
6483   byte len, ncci_state;
6484   word msg;
6485   word info = 0;
6486   word fax_feature_bits;
6487   byte fax_send_edata_ack;
6488   static byte v120_header_buffer[2 + 3];
6489   static word fax_info[] = {
6490     0,                     /* T30_SUCCESS                        */
6491     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6492     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6493     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6494     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6495     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6496     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6497     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6498     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6499     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6500     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6501     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6502     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6503     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6504     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6505     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6506     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6507     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6508     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6509     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6510     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6511     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6512     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6513     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6514     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6516     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6517     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6518     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6519     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6520     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6521     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6522     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6523     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6524     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6525     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6526     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6527     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6528     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6529     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6530     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6531     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6532     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6533     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6534     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6535     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6536     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6537   };
6538
6539     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6540
6541
6542   static word rtp_info[] = {
6543     GOOD,                  /* RTP_SUCCESS                       */
6544     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6545   };
6546
6547   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6548   {
6549     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6550     0x00000000, 0x00000000, 0x00000000, 0x00000000
6551   };
6552
6553   ch = plci->NL.IndCh;
6554   a = plci->adapter;
6555   ncci = a->ch_ncci[ch];
6556   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6557   if(plci->tel) Id|=EXT_CONTROLLER;
6558   APPLptr = plci->appl;
6559   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",
6560     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6561
6562   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6563
6564   if (plci->nl_remove_id)
6565   {
6566     plci->NL.RNR = 2; /* discard */
6567     dbug(1,dprintf("NL discard while remove pending"));
6568     return;
6569   }
6570   if((plci->NL.Ind &0x0f)==N_CONNECT)
6571   {
6572     if(plci->State==INC_DIS_PENDING
6573     || plci->State==OUTG_DIS_PENDING
6574     || plci->State==IDLE)
6575     {
6576       plci->NL.RNR = 2; /* discard */
6577       dbug(1,dprintf("discard n_connect"));
6578       return;
6579     }
6580     if(plci->State < INC_ACT_PENDING)
6581     {
6582       plci->NL.RNR = 1; /* flow control */
6583       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6584       return;
6585     }
6586   }
6587
6588   if(!APPLptr)                         /* no application or invalid data */
6589   {                                    /* while reloading the DSP        */
6590     dbug(1,dprintf("discard1"));
6591     plci->NL.RNR = 2;
6592     return;
6593   }
6594
6595   if (((plci->NL.Ind &0x0f) == N_UDATA)
6596      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6597         || (plci->B2_prot == 7)
6598         || (plci->B3_prot == 7)) )
6599   {
6600     plci->ncpi_buffer[0] = 0;
6601
6602     ncpi_state = plci->ncpi_state;
6603     if (plci->NL.complete == 1)
6604     {
6605       byte  * data = &plci->NL.RBuffer->P[0];
6606
6607       if ((plci->NL.RBuffer->length >= 12)
6608         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6609           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6610       {
6611         word conn_opt, ncpi_opt = 0x00;
6612 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6613
6614         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6615           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6616         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6617           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6618
6619         data++;    /* indication code */
6620         data += 2; /* timestamp */
6621         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6622           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6623         data++;    /* connected norm */
6624         conn_opt = GET_WORD(data);
6625         data += 2; /* connected options */
6626
6627         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6628
6629         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6630         {
6631           ncpi_opt |= MDM_NCPI_ECM_V42;
6632         }
6633         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6634         {
6635           ncpi_opt |= MDM_NCPI_ECM_MNP;
6636         }
6637         else
6638         {
6639           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6640         }
6641         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6642         {
6643           ncpi_opt |= MDM_NCPI_COMPRESSED;
6644         }
6645         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6646         plci->ncpi_buffer[0] = 4;
6647
6648         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6649       }
6650     }
6651     if (plci->B3_prot == 7)
6652     {
6653       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6654        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6655        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6656       {
6657         a->ncci_state[ncci] = INC_ACT_PENDING;
6658         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6659         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6660       }
6661     }
6662
6663     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6664         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6665      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6666      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6667
6668     {
6669       plci->NL.RNR = 2;
6670       return;
6671     }
6672   }
6673
6674   if(plci->NL.complete == 2)
6675     {
6676     if (((plci->NL.Ind &0x0f) == N_UDATA)
6677      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6678     {
6679       switch(plci->RData[0].P[0])
6680       {
6681
6682       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6683         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6684           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6685         break;
6686       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6687         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6688           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6689         break;
6690       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6691         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6692         break;
6693       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6694         dtmf_confirmation (Id, plci);
6695         break;
6696
6697
6698       case UDATA_INDICATION_MIXER_TAP_DATA:
6699         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6700  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6701  if (i != 0)
6702  {
6703    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6704           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6705  }
6706         break;
6707
6708
6709       case UDATA_INDICATION_MIXER_COEFS_SET:
6710         mixer_indication_coefs_set (Id, plci);
6711         break;
6712       case UDATA_INDICATION_XCONNECT_FROM:
6713         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714         break;
6715       case UDATA_INDICATION_XCONNECT_TO:
6716         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6717         break;
6718
6719
6720       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6721         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6722         break;
6723
6724
6725
6726       default:
6727         break;
6728       }
6729     }
6730     else
6731   {
6732       if ((plci->RData[0].PLength != 0)
6733      && ((plci->B2_prot == B2_V120_ASYNC)
6734       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6735       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6736     {
6737
6738       sendf(plci->appl,_DATA_B3_I,Id,0,
6739             "dwww",
6740             plci->RData[1].P,
6741               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6742             plci->RNum,
6743             plci->RFlags);
6744
6745     }
6746     else
6747     {
6748
6749       sendf(plci->appl,_DATA_B3_I,Id,0,
6750             "dwww",
6751             plci->RData[0].P,
6752             plci->RData[0].PLength,
6753             plci->RNum,
6754             plci->RFlags);
6755
6756     }
6757     }
6758     return;
6759   }
6760
6761   fax_feature_bits = 0;
6762   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6763      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6764      (plci->NL.Ind &0x0f)==N_DISC ||
6765      (plci->NL.Ind &0x0f)==N_EDATA ||
6766      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6767   {
6768     info = 0;
6769     plci->ncpi_buffer[0] = 0;
6770     switch (plci->B3_prot) {
6771     case  0: /*XPARENT*/
6772     case  1: /*T.90 NL*/
6773       break;    /* no network control protocol info - jfr */
6774     case  2: /*ISO8202*/
6775     case  3: /*X25 DCE*/
6776       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6777       plci->ncpi_buffer[0] = (byte)(i+3);
6778       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6779       plci->ncpi_buffer[2] = 0;
6780       plci->ncpi_buffer[3] = 0;
6781       break;
6782     case  4: /*T.30 - FAX*/
6783     case  5: /*T.30 - FAX*/
6784       if(plci->NL.RLength>=sizeof(T30_INFO))
6785       {
6786         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6787         len = 9;
6788         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6789         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6790         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6791         if (plci->B3_prot == 5)
6792         {
6793           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6794             i |= 0x8000; /* This is not an ECM connection */
6795           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6796             i |= 0x4000; /* This is a connection with MMR compression */
6797           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6798             i |= 0x2000; /* This is a connection with MR compression */
6799           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6800             i |= 0x0004; /* More documents */
6801           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6802             i |= 0x0002; /* Fax-polling indication */
6803         }
6804         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6805         PUT_WORD(&(plci->ncpi_buffer[3]),i);
6806         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6807         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6808         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6809         plci->ncpi_buffer[len] = 0;
6810         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6811         {
6812           plci->ncpi_buffer[len] = 20;
6813           for (i = 0; i < 20; i++)
6814             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6815         }
6816         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6817         {
6818           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6819             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6820           else
6821             info = _FAX_PROTOCOL_ERROR;
6822         }
6823
6824         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6825           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6826         {
6827           i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6828           while (i < plci->NL.RBuffer->length)
6829             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6830         }
6831
6832         plci->ncpi_buffer[0] = len;
6833         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6834         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6835
6836         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6837  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6838          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6839           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6840          || (((plci->NL.Ind &0x0f) == N_EDATA)
6841           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6842            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6843            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6844  {
6845           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6846  }
6847  if (((plci->NL.Ind &0x0f) == N_DISC)
6848   || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6849   || (((plci->NL.Ind &0x0f) == N_EDATA)
6850    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6851  {
6852           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6853  }
6854       }
6855       break;
6856
6857     case B3_RTP:
6858       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6859       {
6860         if (plci->NL.RLength != 0)
6861         {
6862           info = rtp_info[plci->NL.RBuffer->P[0]];
6863           plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6864           for (i = 1; i < plci->NL.RLength; i++)
6865             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6866         }
6867       }
6868       break;
6869
6870     }
6871     plci->NL.RNR = 2;
6872   }
6873   switch(plci->NL.Ind &0x0f) {
6874   case N_EDATA:
6875     if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6876     {
6877       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6878         ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6879       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6880
6881       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6882        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6883        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6884        && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6885        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6886        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6887       {
6888         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6889         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6890           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6891         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6892  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6893    fax_send_edata_ack = false;
6894       }
6895
6896       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6897       {
6898         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6899         {
6900         case EDATA_T30_DIS:
6901           if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6902            && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6903            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6904            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6905           {
6906             a->ncci_state[ncci] = INC_ACT_PENDING;
6907             if (plci->B3_prot == 4)
6908               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6909             else
6910               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6911             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6912           }
6913           break;
6914
6915         case EDATA_T30_TRAIN_OK:
6916           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6917            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6919           {
6920             if (plci->B3_prot == 4)
6921               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6922             else
6923               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6924             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6925           }
6926           break;
6927
6928         case EDATA_T30_EOP_CAPI:
6929           if (a->ncci_state[ncci] == CONNECTED)
6930           {
6931             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6932             a->ncci_state[ncci] = INC_DIS_PENDING;
6933             plci->ncpi_state = 0;
6934      fax_send_edata_ack = false;
6935           }
6936           break;
6937         }
6938       }
6939       else
6940       {
6941         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6942         {
6943         case EDATA_T30_TRAIN_OK:
6944           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6945            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6946            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6947           {
6948             if (plci->B3_prot == 4)
6949               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6950             else
6951               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6952             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6953           }
6954           break;
6955         }
6956       }
6957       if (fax_send_edata_ack)
6958       {
6959         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6960  plci->fax_edata_ack_length = 1;
6961         start_internal_command (Id, plci, fax_edata_ack_command);
6962       }
6963     }
6964     else
6965     {
6966       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6967     }
6968     break;
6969   case N_CONNECT:
6970     if (!a->ch_ncci[ch])
6971     {
6972       ncci = get_ncci (plci, ch, 0);
6973       Id = (Id & 0xffff) | (((dword) ncci) << 16);
6974     }
6975     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6976       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6977
6978     msg = _CONNECT_B3_I;
6979     if (a->ncci_state[ncci] == IDLE)
6980       plci->channels++;
6981     else if (plci->B3_prot == 1)
6982       msg = _CONNECT_B3_T90_ACTIVE_I;
6983
6984     a->ncci_state[ncci] = INC_CON_PENDING;
6985     if(plci->B3_prot == 4)
6986       sendf(plci->appl,msg,Id,0,"s","");
6987     else
6988       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6989     break;
6990   case N_CONNECT_ACK:
6991     dbug(1,dprintf("N_connect_Ack"));
6992     if (plci->internal_command_queue[0]
6993      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6994       || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6995       || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6996     {
6997       (*(plci->internal_command_queue[0]))(Id, plci, 0);
6998       if (!plci->internal_command)
6999         next_internal_command (Id, plci);
7000       break;
7001     }
7002     msg = _CONNECT_B3_ACTIVE_I;
7003     if (plci->B3_prot == 1)
7004     {
7005       if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7006         msg = _CONNECT_B3_T90_ACTIVE_I;
7007       a->ncci_state[ncci] = INC_ACT_PENDING;
7008       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7009     }
7010     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7011     {
7012       if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7013        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7014        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7015       {
7016         a->ncci_state[ncci] = INC_ACT_PENDING;
7017         if (plci->B3_prot == 4)
7018           sendf(plci->appl,msg,Id,0,"s","");
7019         else
7020           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7021         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7022       }
7023     }
7024     else
7025     {
7026       a->ncci_state[ncci] = INC_ACT_PENDING;
7027       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7028     }
7029     if (plci->adjust_b_restore)
7030     {
7031       plci->adjust_b_restore = false;
7032       start_internal_command (Id, plci, adjust_b_restore);
7033     }
7034     break;
7035   case N_DISC:
7036   case N_DISC_ACK:
7037     if (plci->internal_command_queue[0]
7038      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7039       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7040       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7041     {
7042       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7043       if (!plci->internal_command)
7044         next_internal_command (Id, plci);
7045     }
7046     ncci_state = a->ncci_state[ncci];
7047     ncci_remove (plci, ncci, false);
7048
7049         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7050         /* channel, so we cannot store the state in ncci_state! The */
7051         /* information which channel we received a N_DISC is thus   */
7052         /* stored in the inc_dis_ncci_table buffer.                 */
7053     for(i=0; plci->inc_dis_ncci_table[i]; i++);
7054     plci->inc_dis_ncci_table[i] = (byte) ncci;
7055
7056       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7057     if (!plci->channels
7058      && (plci->B1_resource == 16)
7059      && (plci->State <= CONNECTED))
7060     {
7061       len = 9;
7062       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7063       PUT_WORD (&plci->ncpi_buffer[1], i);
7064       PUT_WORD (&plci->ncpi_buffer[3], 0);
7065       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7066       PUT_WORD (&plci->ncpi_buffer[5], i);
7067       PUT_WORD (&plci->ncpi_buffer[7], 0);
7068       plci->ncpi_buffer[len] = 0;
7069       plci->ncpi_buffer[0] = len;
7070       if(plci->B3_prot == 4)
7071         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7072       else
7073       {
7074
7075         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7076           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7077         {
7078           plci->ncpi_buffer[++len] = 0;
7079           plci->ncpi_buffer[++len] = 0;
7080           plci->ncpi_buffer[++len] = 0;
7081           plci->ncpi_buffer[0] = len;
7082         }
7083
7084         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7085       }
7086       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7087       plci->ncpi_state = 0;
7088       sig_req(plci,HANGUP,0);
7089       send_req(plci);
7090       plci->State = OUTG_DIS_PENDING;
7091       /* disc here */
7092     }
7093     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7094      && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7095      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7096     {
7097       if (ncci_state == IDLE)
7098       {
7099         if (plci->channels)
7100           plci->channels--;
7101         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7102           if(plci->State == SUSPENDING){
7103             sendf(plci->appl,
7104                   _FACILITY_I,
7105                   Id & 0xffffL,
7106                   0,
7107                   "ws", (word)3, "\x03\x04\x00\x00");
7108             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7109           }
7110           plci_remove(plci);
7111           plci->State=IDLE;
7112         }
7113       }
7114     }
7115     else if (plci->channels)
7116     {
7117       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7118       plci->ncpi_state = 0;
7119       if ((ncci_state == OUTG_REJ_PENDING)
7120        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7121       {
7122         sig_req(plci,HANGUP,0);
7123         send_req(plci);
7124         plci->State = OUTG_DIS_PENDING;
7125       }
7126     }
7127     break;
7128   case N_RESET:
7129     a->ncci_state[ncci] = INC_RES_PENDING;
7130     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7131     break;
7132   case N_RESET_ACK:
7133     a->ncci_state[ncci] = CONNECTED;
7134     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7135     break;
7136
7137   case N_UDATA:
7138     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7139     {
7140       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7141       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7142       plci->NL.R = plci->RData;
7143       plci->NL.RNum = 1;
7144       return;
7145     }
7146   case N_BDATA:
7147   case N_DATA:
7148     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7149      || (a->ncci_state[ncci] == IDLE)
7150      || (a->ncci_state[ncci] == INC_DIS_PENDING))
7151     {
7152       plci->NL.RNR = 2;
7153       break;
7154     }
7155     if ((a->ncci_state[ncci] != CONNECTED)
7156      && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7157      && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7158     {
7159       dbug(1,dprintf("flow control"));
7160       plci->NL.RNR = 1; /* flow control  */
7161       channel_x_off (plci, ch, 0);
7162       break;
7163     }
7164
7165     NCCIcode = ncci | (((word)a->Id) << 8);
7166
7167                 /* count all buffers within the Application pool    */
7168                 /* belonging to the same NCCI. If this is below the */
7169                 /* number of buffers available per NCCI we accept   */
7170                 /* this packet, otherwise we reject it              */
7171     count = 0;
7172     Num = 0xffff;
7173     for(i=0; i<APPLptr->MaxBuffer; i++) {
7174       if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7175       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7176     }
7177
7178     if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7179     {
7180       dbug(3,dprintf("Flow-Control"));
7181       plci->NL.RNR = 1;
7182       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7183        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7184       {
7185         plci->NL.RNR = 2;
7186         dbug(3,dprintf("DiscardData"));
7187       } else {
7188         channel_x_off (plci, ch, 0);
7189       }
7190       break;
7191     }
7192     else
7193     {
7194       APPLptr->NCCIDataFlowCtrlTimer = 0;
7195     }
7196
7197     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7198     if(!plci->RData[0].P) {
7199       plci->NL.RNR = 1;
7200       channel_x_off (plci, ch, 0);
7201       break;
7202     }
7203
7204     APPLptr->DataNCCI[Num] = NCCIcode;
7205     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7206     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7207
7208     plci->RNum = Num;
7209     plci->RFlags = plci->NL.Ind>>4;
7210     plci->RData[0].PLength = APPLptr->MaxDataLength;
7211     plci->NL.R = plci->RData;
7212     if ((plci->NL.RLength != 0)
7213      && ((plci->B2_prot == B2_V120_ASYNC)
7214       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7215       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7216     {
7217       plci->RData[1].P = plci->RData[0].P;
7218       plci->RData[1].PLength = plci->RData[0].PLength;
7219       plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7220       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7221         plci->RData[0].PLength = 1;
7222       else
7223         plci->RData[0].PLength = 2;
7224       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7225         plci->RFlags |= 0x0010;
7226       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7227         plci->RFlags |= 0x8000;
7228       plci->NL.RNum = 2;
7229     }
7230     else
7231     {
7232       if((plci->NL.Ind &0x0f)==N_UDATA)
7233         plci->RFlags |= 0x0010;
7234
7235       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7236         plci->RFlags |= 0x0001;
7237
7238       plci->NL.RNum = 1;
7239     }
7240     break;
7241   case N_DATA_ACK:
7242     data_ack (plci, ch);
7243     break;
7244   default:
7245     plci->NL.RNR = 2;
7246     break;
7247   }
7248 }
7249
7250 /*------------------------------------------------------------------*/
7251 /* find a free PLCI                                                 */
7252 /*------------------------------------------------------------------*/
7253
7254 static word get_plci(DIVA_CAPI_ADAPTER *a)
7255 {
7256   word i,j;
7257   PLCI   * plci;
7258
7259   dump_plcis (a);
7260   for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7261   if(i==a->max_plci) {
7262     dbug(1,dprintf("get_plci: out of PLCIs"));
7263     return 0;
7264   }
7265   plci = &a->plci[i];
7266   plci->Id = (byte)(i+1);
7267
7268   plci->Sig.Id = 0;
7269   plci->NL.Id = 0;
7270   plci->sig_req = 0;
7271   plci->nl_req = 0;
7272
7273   plci->appl = NULL;
7274   plci->relatedPTYPLCI = NULL;
7275   plci->State = IDLE;
7276   plci->SuppState = IDLE;
7277   plci->channels = 0;
7278   plci->tel = 0;
7279   plci->B1_resource = 0;
7280   plci->B2_prot = 0;
7281   plci->B3_prot = 0;
7282
7283   plci->command = 0;
7284   plci->m_command = 0;
7285   init_internal_command_queue (plci);
7286   plci->number = 0;
7287   plci->req_in_start = 0;
7288   plci->req_in = 0;
7289   plci->req_out = 0;
7290   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7291   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7292   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7293
7294   plci->data_sent = false;
7295   plci->send_disc = 0;
7296   plci->sig_global_req = 0;
7297   plci->sig_remove_id = 0;
7298   plci->nl_global_req = 0;
7299   plci->nl_remove_id = 0;
7300   plci->adv_nl = 0;
7301   plci->manufacturer = false;
7302   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7303   plci->spoofed_msg = 0;
7304   plci->ptyState = 0;
7305   plci->cr_enquiry = false;
7306   plci->hangup_flow_ctrl_timer = 0;
7307
7308   plci->ncci_ring_list = 0;
7309   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7310   clear_c_ind_mask (plci);
7311   set_group_ind_mask (plci);
7312   plci->fax_connect_info_length = 0;
7313   plci->nsf_control_bits = 0;
7314   plci->ncpi_state = 0x00;
7315   plci->ncpi_buffer[0] = 0;
7316
7317   plci->requested_options_conn = 0;
7318   plci->requested_options = 0;
7319   plci->notifiedcall = 0;
7320   plci->vswitchstate = 0;
7321   plci->vsprot = 0;
7322   plci->vsprotdialect = 0;
7323   init_b1_config (plci);
7324   dbug(1,dprintf("get_plci(%x)",plci->Id));
7325   return i+1;
7326 }
7327
7328 /*------------------------------------------------------------------*/
7329 /* put a parameter in the parameter buffer                          */
7330 /*------------------------------------------------------------------*/
7331
7332 static void add_p(PLCI   * plci, byte code, byte   * p)
7333 {
7334   word p_length;
7335
7336   p_length = 0;
7337   if(p) p_length = p[0];
7338   add_ie(plci, code, p, p_length);
7339 }
7340
7341 /*------------------------------------------------------------------*/
7342 /* put a structure in the parameter buffer                          */
7343 /*------------------------------------------------------------------*/
7344 static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7345 {
7346   if(p) add_ie(plci, code, p->info, (word)p->length);
7347 }
7348
7349 /*------------------------------------------------------------------*/
7350 /* put multiple structures in the parameter buffer                  */
7351 /*------------------------------------------------------------------*/
7352 static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7353 {
7354   byte i;
7355
7356   if(p){
7357     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7358     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7359       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7360       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7361     }
7362   }
7363 }
7364
7365 /*------------------------------------------------------------------*/
7366 /* return the channel number sent by the application in a esc_chi   */
7367 /*------------------------------------------------------------------*/
7368 static byte getChannel(API_PARSE * p)
7369 {
7370   byte i;
7371
7372   if(p){
7373     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7374       if(p->info[i]==2){
7375         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7376       }
7377     }
7378   }
7379   return 0;
7380 }
7381
7382
7383 /*------------------------------------------------------------------*/
7384 /* put an information element in the parameter buffer               */
7385 /*------------------------------------------------------------------*/
7386
7387 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7388 {
7389   word i;
7390
7391   if(!(code &0x80) && !p_length) return;
7392
7393   if(plci->req_in==plci->req_in_start) {
7394     plci->req_in +=2;
7395   }
7396   else {
7397     plci->req_in--;
7398   }
7399   plci->RBuffer[plci->req_in++] = code;
7400
7401   if(p) {
7402     plci->RBuffer[plci->req_in++] = (byte)p_length;
7403     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7404   }
7405
7406   plci->RBuffer[plci->req_in++] = 0;
7407 }
7408
7409 /*------------------------------------------------------------------*/
7410 /* put a unstructured data into the buffer                          */
7411 /*------------------------------------------------------------------*/
7412
7413 static void add_d(PLCI *plci, word length, byte *p)
7414 {
7415   word i;
7416
7417   if(plci->req_in==plci->req_in_start) {
7418     plci->req_in +=2;
7419   }
7420   else {
7421     plci->req_in--;
7422   }
7423   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7424 }
7425
7426 /*------------------------------------------------------------------*/
7427 /* put parameters from the Additional Info parameter in the         */
7428 /* parameter buffer                                                 */
7429 /*------------------------------------------------------------------*/
7430
7431 static void add_ai(PLCI *plci, API_PARSE *ai)
7432 {
7433   word i;
7434     API_PARSE ai_parms[5];
7435
7436   for(i=0;i<5;i++) ai_parms[i].length = 0;
7437
7438   if(!ai->length)
7439     return;
7440   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7441     return;
7442
7443   add_s (plci,KEY,&ai_parms[1]);
7444   add_s (plci,UUI,&ai_parms[2]);
7445   add_ss(plci,FTY,&ai_parms[3]);
7446 }
7447
7448 /*------------------------------------------------------------------*/
7449 /* put parameter for b1 protocol in the parameter buffer            */
7450 /*------------------------------------------------------------------*/
7451
7452 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7453                    word b1_facilities)
7454 {
7455     API_PARSE bp_parms[8];
7456     API_PARSE mdm_cfg[9];
7457     API_PARSE global_config[2];
7458     byte cai[256];
7459   byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7460   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7461   word i;
7462
7463     API_PARSE mdm_cfg_v18[4];
7464   word j, n, w;
7465   dword d;
7466
7467
7468   for(i=0;i<8;i++) bp_parms[i].length = 0;
7469   for(i=0;i<2;i++) global_config[i].length = 0;
7470
7471   dbug(1,dprintf("add_b1"));
7472   api_save_msg(bp, "s", &plci->B_protocol);
7473
7474   if(b_channel_info==2){
7475     plci->B1_resource = 0;
7476     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7477     add_p(plci, CAI, "\x01\x00");
7478     dbug(1,dprintf("Cai=1,0 (no resource)"));
7479     return 0;
7480   }
7481
7482   if(plci->tel == CODEC_PERMANENT) return 0;
7483   else if(plci->tel == CODEC){
7484     plci->B1_resource = 1;
7485     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7486     add_p(plci, CAI, "\x01\x01");
7487     dbug(1,dprintf("Cai=1,1 (Codec)"));
7488     return 0;
7489   }
7490   else if(plci->tel == ADV_VOICE){
7491     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7492     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7493     voice_cai[1] = plci->B1_resource;
7494     PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7495     add_p(plci, CAI, voice_cai);
7496     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7497     return 0;
7498   }
7499   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7500   if (plci->call_dir & CALL_DIR_OUT)
7501     plci->call_dir |= CALL_DIR_ORIGINATE;
7502   else if (plci->call_dir & CALL_DIR_IN)
7503     plci->call_dir |= CALL_DIR_ANSWER;
7504
7505   if(!bp->length){
7506     plci->B1_resource = 0x5;
7507     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7508     add_p(plci, CAI, "\x01\x05");
7509     return 0;
7510   }
7511
7512   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7513   if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7514   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7515   {
7516     bp_parms[6].length = 0;
7517     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7518     {
7519       dbug(1,dprintf("b-form.!"));
7520       return _WRONG_MESSAGE_FORMAT;
7521     }
7522   }
7523   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7524   {
7525     dbug(1,dprintf("b-form.!"));
7526     return _WRONG_MESSAGE_FORMAT;
7527   }
7528
7529   if(bp_parms[6].length)
7530   {
7531     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7532     {
7533       return _WRONG_MESSAGE_FORMAT;
7534     }
7535     switch(GET_WORD(global_config[0].info))
7536     {
7537     case 1:
7538       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7539       break;
7540     case 2:
7541       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7542       break;
7543     }
7544   }
7545   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7546
7547
7548   if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7549    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7550   {
7551     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7552     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7553     cai[1] = plci->B1_resource;
7554     cai[2] = 0;
7555     cai[3] = 0;
7556     cai[4] = 0;
7557     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7558     for (i = 0; i < bp_parms[3].length; i++)
7559       cai[7+i] = bp_parms[3].info[1+i];
7560     cai[0] = 6 + bp_parms[3].length;
7561     add_p(plci, CAI, cai);
7562     return 0;
7563   }
7564
7565
7566   if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7567    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7568   {
7569     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7570     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7571     cai[1] = plci->B1_resource;
7572     cai[2] = 0;
7573     cai[3] = 0;
7574     cai[4] = 0;
7575     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7576     cai[0] = 6;
7577     add_p(plci, CAI, cai);
7578     return 0;
7579   }
7580
7581
7582   if ((GET_WORD(bp_parms[0].info) >= 32)
7583    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7584     && ((GET_WORD(bp_parms[0].info) != 3)
7585      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7586      || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7587   {
7588     return _B1_NOT_SUPPORTED;
7589   }
7590   plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7591     (word)(b1_facilities & ~B1_FACILITY_VOICE));
7592   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7593   cai[0] = 6;
7594   cai[1] = plci->B1_resource;
7595   for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7596
7597   if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7598    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7599    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7600   { /* B1 - modem */
7601     for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7602
7603     if (bp_parms[3].length)
7604     {
7605       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7606       {
7607         return (_WRONG_MESSAGE_FORMAT);
7608       }
7609         
7610       cai[2] = 0; /* Bit rate for adaptation */
7611
7612       dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7613
7614       PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
7615       PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7616       PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
7617       PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7618
7619       cai[3] = 0; /* Async framing parameters */
7620       switch (GET_WORD (mdm_cfg[2].info))
7621       {       /* Parity     */
7622       case 1: /* odd parity */
7623         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7624         dbug(1,dprintf("MDM: odd parity"));
7625         break;
7626
7627       case 2: /* even parity */
7628         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7629         dbug(1,dprintf("MDM: even parity"));
7630         break;
7631
7632       default:
7633         dbug(1,dprintf("MDM: no parity"));
7634         break;
7635       }
7636
7637       switch (GET_WORD (mdm_cfg[3].info))
7638       {       /* stop bits   */
7639       case 1: /* 2 stop bits */
7640         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7641         dbug(1,dprintf("MDM: 2 stop bits"));
7642         break;
7643
7644       default:
7645         dbug(1,dprintf("MDM: 1 stop bit"));
7646         break;
7647       }
7648
7649       switch (GET_WORD (mdm_cfg[1].info))
7650       {     /* char length */
7651       case 5:
7652         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7653         dbug(1,dprintf("MDM: 5 bits"));
7654         break;
7655
7656       case 6:
7657         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7658         dbug(1,dprintf("MDM: 6 bits"));
7659         break;
7660
7661       case 7:
7662         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7663         dbug(1,dprintf("MDM: 7 bits"));
7664         break;
7665
7666       default:
7667         dbug(1,dprintf("MDM: 8 bits"));
7668         break;
7669       }
7670
7671       cai[7] = 0; /* Line taking options */
7672       cai[8] = 0; /* Modulation negotiation options */
7673       cai[9] = 0; /* Modulation options */
7674
7675       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7676       {
7677         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7678         dbug(1, dprintf("MDM: Reverse direction"));
7679       }
7680
7681       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7682       {
7683         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7684         dbug(1, dprintf("MDM: Disable retrain"));
7685       }
7686
7687       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7688       {
7689         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7690         dbug(1, dprintf("MDM: Disable ring tone"));
7691       }
7692
7693       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7694       {
7695         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7696         dbug(1, dprintf("MDM: 1800 guard tone"));
7697       }
7698       else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7699       {
7700         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7701         dbug(1, dprintf("MDM: 550 guard tone"));
7702       }
7703
7704       if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7705       {
7706         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7707         dbug(1, dprintf("MDM: V100"));
7708       }
7709       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7710       {
7711         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7712         dbug(1, dprintf("MDM: IN CLASS"));
7713       }
7714       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7715       {
7716         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7717         dbug(1, dprintf("MDM: DISABLED"));
7718       }
7719       cai[0] = 20;
7720
7721       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7722        && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7723       {
7724         plci->requested_options |= 1L << PRIVATE_V18;
7725       }
7726       if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7727         plci->requested_options |= 1L << PRIVATE_VOWN;
7728
7729       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7730         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7731       {
7732         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7733         {
7734           i = 27;
7735           if (mdm_cfg[6].length >= 4)
7736           {
7737             d = GET_DWORD(&mdm_cfg[6].info[1]);
7738             cai[7] |= (byte) d;          /* line taking options */
7739             cai[9] |= (byte)(d >> 8);    /* modulation options */
7740             cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7741             cai[++i] = (byte)(d >> 24);
7742             if (mdm_cfg[6].length >= 8)
7743             {
7744               d = GET_DWORD(&mdm_cfg[6].info[5]);
7745               cai[10] |= (byte) d;        /* disabled modulations mask */
7746               cai[11] |= (byte)(d >> 8);
7747               if (mdm_cfg[6].length >= 12)
7748               {
7749                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7750                 cai[12] = (byte) d;          /* enabled modulations mask */
7751                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7752                 cai[++i] = (byte)(d >> 16);
7753                 cai[++i] = (byte)(d >> 24);
7754                 cai[++i] = 0;
7755                 if (mdm_cfg[6].length >= 14)
7756                 {
7757                   w = GET_WORD(&mdm_cfg[6].info[13]);
7758                   if (w != 0)
7759                     PUT_WORD(&cai[13], w);  /* min tx speed */
7760                   if (mdm_cfg[6].length >= 16)
7761                   {
7762                     w = GET_WORD(&mdm_cfg[6].info[15]);
7763                     if (w != 0)
7764                       PUT_WORD(&cai[15], w);  /* max tx speed */
7765                     if (mdm_cfg[6].length >= 18)
7766                     {
7767                       w = GET_WORD(&mdm_cfg[6].info[17]);
7768                       if (w != 0)
7769                         PUT_WORD(&cai[17], w);  /* min rx speed */
7770                       if (mdm_cfg[6].length >= 20)
7771                       {
7772                         w = GET_WORD(&mdm_cfg[6].info[19]);
7773                         if (w != 0)
7774                           PUT_WORD(&cai[19], w);  /* max rx speed */
7775                         if (mdm_cfg[6].length >= 22)
7776                         {
7777                           w = GET_WORD(&mdm_cfg[6].info[21]);
7778                           cai[23] = (byte)(-((short) w));  /* transmit level */
7779                           if (mdm_cfg[6].length >= 24)
7780                           {
7781                             w = GET_WORD(&mdm_cfg[6].info[23]);
7782                             cai[22] |= (byte) w;        /* info options mask */
7783                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7784                           }
7785                         }
7786                       }
7787                     }
7788                   }
7789                 }
7790               }
7791             }
7792           }
7793           cai[27] = i - 27;
7794           i++;
7795           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7796           {
7797             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7798             {
7799               for (n = 0; n < 3; n++)
7800               {
7801                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7802                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7803                   cai[i+j] = mdm_cfg_v18[n].info[j];
7804                 i += cai[i] + 1;
7805               }
7806             }
7807           }
7808           cai[0] = (byte)(i - 1);
7809         }
7810       }
7811
7812     }
7813   }
7814   if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
7815      GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
7816   {
7817     if(bp_parms[3].length){
7818       dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7819       switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
7820         case 0:
7821         case 56000:
7822           if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
7823             dbug(1,dprintf("56k sync HSCX"));
7824             cai[1] = 8;
7825             cai[2] = 0;
7826             cai[3] = 0;
7827           }
7828           else if(GET_WORD(bp_parms[0].info)==2){
7829             dbug(1,dprintf("56k async DSP"));
7830             cai[2] = 9;
7831           }
7832           break;
7833         case 50:     cai[2] = 1;  break;
7834         case 75:     cai[2] = 1;  break;
7835         case 110:    cai[2] = 1;  break;
7836         case 150:    cai[2] = 1;  break;
7837         case 200:    cai[2] = 1;  break;
7838         case 300:    cai[2] = 1;  break;
7839         case 600:    cai[2] = 1;  break;
7840         case 1200:   cai[2] = 2;  break;
7841         case 2400:   cai[2] = 3;  break;
7842         case 4800:   cai[2] = 4;  break;
7843         case 7200:   cai[2] = 10; break;
7844         case 9600:   cai[2] = 5;  break;
7845         case 12000:  cai[2] = 13; break;
7846         case 24000:  cai[2] = 0;  break;
7847         case 14400:  cai[2] = 11; break;
7848         case 19200:  cai[2] = 6;  break;
7849         case 28800:  cai[2] = 12; break;
7850         case 38400:  cai[2] = 7;  break;
7851         case 48000:  cai[2] = 8;  break;
7852         case 76:     cai[2] = 15; break;  /* 75/1200     */
7853         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7854         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7855
7856         default:
7857           return _B1_PARM_NOT_SUPPORTED;
7858       }
7859       cai[3] = 0;
7860       if (cai[1] == 13)                                        /* v.110 async */
7861       {
7862         if (bp_parms[3].length >= 8)
7863         {
7864           switch (GET_WORD (&bp_parms[3].info[3]))
7865           {       /* char length */
7866           case 5:
7867             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7868             break;
7869           case 6:
7870             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7871             break;
7872           case 7:
7873             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7874             break;
7875           }
7876           switch (GET_WORD (&bp_parms[3].info[5]))
7877           {       /* Parity     */
7878           case 1: /* odd parity */
7879             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7880             break;
7881           case 2: /* even parity */
7882             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7883             break;
7884           }
7885           switch (GET_WORD (&bp_parms[3].info[7]))
7886           {       /* stop bits   */
7887           case 1: /* 2 stop bits */
7888             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7889             break;
7890           }
7891         }
7892       }
7893     }
7894     else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7895       dbug(1,dprintf("V.110 default 56k sync"));
7896       cai[1] = 8;
7897       cai[2] = 0;
7898       cai[3] = 0;
7899     }
7900     else {
7901       dbug(1,dprintf("V.110 default 9600 async"));
7902       cai[2] = 5;
7903     }
7904   }
7905   PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7906   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]));
7907 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7908
7909   add_p(plci, CAI, cai);
7910   return 0;
7911 }
7912
7913 /*------------------------------------------------------------------*/
7914 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7915 /*------------------------------------------------------------------*/
7916
7917 static word add_b23(PLCI *plci, API_PARSE *bp)
7918 {
7919   word i, fax_control_bits;
7920   byte pos, len;
7921   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7922     API_PARSE bp_parms[8];
7923   API_PARSE * b1_config;
7924   API_PARSE * b2_config;
7925     API_PARSE b2_config_parms[8];
7926   API_PARSE * b3_config;
7927     API_PARSE b3_config_parms[6];
7928     API_PARSE global_config[2];
7929
7930   static byte llc[3] = {2,0,0};
7931   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7932   static byte nlc[256];
7933   static byte lli[12] = {1,1};
7934
7935   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7936   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7937
7938   const byte llc3[] = {4,3,2,2,6,6,0};
7939   const byte header[] = {0,2,3,3,0,0,0};
7940
7941   for(i=0;i<8;i++) bp_parms[i].length = 0;
7942   for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7943   for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7944
7945   lli[0] = 1;
7946   lli[1] = 1;
7947   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7948     lli[1] |= 2;
7949   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7950     lli[1] |= 4;
7951
7952   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7953     lli[1] |= 0x10;
7954     if (plci->rx_dma_descriptor <= 0) {
7955       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7956       if (plci->rx_dma_descriptor >= 0)
7957         plci->rx_dma_descriptor++;
7958     }
7959     if (plci->rx_dma_descriptor > 0) {
7960       lli[0] = 6;
7961       lli[1] |= 0x40;
7962       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7963       lli[3] = (byte)plci->rx_dma_magic;
7964       lli[4] = (byte)(plci->rx_dma_magic >>  8);
7965       lli[5] = (byte)(plci->rx_dma_magic >> 16);
7966       lli[6] = (byte)(plci->rx_dma_magic >> 24);
7967     }
7968   }
7969
7970   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7971     lli[1] |= 0x20;
7972   }
7973
7974   dbug(1,dprintf("add_b23"));
7975   api_save_msg(bp, "s", &plci->B_protocol);
7976
7977   if(!bp->length && plci->tel)
7978   {
7979     plci->adv_nl = true;
7980     dbug(1,dprintf("Default adv.Nl"));
7981     add_p(plci,LLI,lli);
7982     plci->B2_prot = 1 /*XPARENT*/;
7983     plci->B3_prot = 0 /*XPARENT*/;
7984     llc[1] = 2;
7985     llc[2] = 4;
7986     add_p(plci, LLC, llc);
7987     dlc[0] = 2;
7988     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7989     add_p(plci, DLC, dlc);
7990     return 0;
7991   }
7992
7993   if(!bp->length) /*default*/
7994   {   
7995     dbug(1,dprintf("ret default"));
7996     add_p(plci,LLI,lli);
7997     plci->B2_prot = 0 /*X.75   */;
7998     plci->B3_prot = 0 /*XPARENT*/;
7999     llc[1] = 1;
8000     llc[2] = 4;
8001     add_p(plci, LLC, llc);
8002     dlc[0] = 2;
8003     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8004     add_p(plci, DLC, dlc);
8005     return 0;
8006   }
8007   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8008   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8009
8010   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8011   {
8012     bp_parms[6].length = 0;
8013     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8014     {
8015       dbug(1,dprintf("b-form.!"));
8016       return _WRONG_MESSAGE_FORMAT;
8017     }
8018   }
8019   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8020   {
8021     dbug(1,dprintf("b-form.!"));
8022     return _WRONG_MESSAGE_FORMAT;
8023   }
8024
8025   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8026   {  
8027     if(GET_WORD(bp_parms[1].info)!=1
8028     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8029     plci->adv_nl = true;
8030   }
8031   else if(plci->tel) return _B2_NOT_SUPPORTED;
8032
8033
8034   if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8035    && (GET_WORD(bp_parms[2].info) == B3_RTP)
8036    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8037   {
8038     add_p(plci,LLI,lli);
8039     plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8040     plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8041     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8042     llc[2] = 4;
8043     add_p(plci, LLC, llc);
8044     dlc[0] = 2;
8045     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8046     dlc[3] = 3; /* Addr A */
8047     dlc[4] = 1; /* Addr B */
8048     dlc[5] = 7; /* modulo mode */
8049     dlc[6] = 7; /* window size */
8050     dlc[7] = 0; /* XID len Lo  */
8051     dlc[8] = 0; /* XID len Hi  */
8052     for (i = 0; i < bp_parms[4].length; i++)
8053       dlc[9+i] = bp_parms[4].info[1+i];
8054     dlc[0] = (byte)(8 + bp_parms[4].length);
8055     add_p(plci, DLC, dlc);
8056     for (i = 0; i < bp_parms[5].length; i++)
8057       nlc[1+i] = bp_parms[5].info[1+i];
8058     nlc[0] = (byte)(bp_parms[5].length);
8059     add_p(plci, NLC, nlc);
8060     return 0;
8061   }
8062
8063
8064
8065   if ((GET_WORD(bp_parms[1].info) >= 32)
8066    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8067     && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8068      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8069
8070   {
8071     return _B2_NOT_SUPPORTED;
8072   }
8073   if ((GET_WORD(bp_parms[2].info) >= 32)
8074    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8075   {
8076     return _B3_NOT_SUPPORTED;
8077   }
8078   if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8079    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8080     || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8081     || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8082   {
8083     return (add_modem_b23 (plci, bp_parms));
8084   }
8085
8086   add_p(plci,LLI,lli);
8087
8088   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8089   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8090   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8091
8092   if(bp_parms[6].length)
8093   {
8094     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8095     {
8096       return _WRONG_MESSAGE_FORMAT;
8097     }
8098     switch(GET_WORD(global_config[0].info))
8099     {
8100     case 1:
8101       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8102       break;
8103     case 2:
8104       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8105       break;
8106     }
8107   }
8108   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8109
8110
8111   if (plci->B2_prot == B2_PIAFS)
8112     llc[1] = PIAFS_CRC;
8113   else
8114 /* IMPLEMENT_PIAFS */
8115   {
8116     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8117              llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8118   }
8119   llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8120
8121   add_p(plci, LLC, llc);
8122
8123   dlc[0] = 2;
8124   PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8125                       header[GET_WORD(bp_parms[2].info)]);
8126
8127   b1_config = &bp_parms[3];
8128   nlc[0] = 0;
8129   if(plci->B3_prot == 4
8130   || plci->B3_prot == 5)
8131   {
8132     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8133     nlc[0] = sizeof(T30_INFO);
8134     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8135       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8136     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8137     if(b1_config->length>=2)
8138     {
8139       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8140     }
8141   }
8142   b2_config = &bp_parms[4];
8143
8144
8145   if (llc[1] == PIAFS_CRC)
8146   {
8147     if (plci->B3_prot != B3_TRANSPARENT)
8148     {
8149       return _B_STACK_NOT_SUPPORTED;
8150     }
8151     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8152       return _WRONG_MESSAGE_FORMAT;
8153     }
8154     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8155     dlc[3] = 0; /* Addr A */
8156     dlc[4] = 0; /* Addr B */
8157     dlc[5] = 0; /* modulo mode */
8158     dlc[6] = 0; /* window size */
8159     if (b2_config->length >= 7){
8160       dlc[ 7] = 7; 
8161       dlc[ 8] = 0; 
8162       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8163       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8164       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8165       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8166       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8167       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8168       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8169       dlc[ 0] = 15;
8170       if(b2_config->length >= 8) { /* PIAFS control abilities */
8171         dlc[ 7] = 10; 
8172         dlc[16] = 2; /* Length of PIAFS extention */
8173         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8174         dlc[18] = b2_config_parms[4].info[0]; /* value */
8175         dlc[ 0] = 18;
8176       }
8177     }
8178     else /* default values, 64K, variable, no compression */
8179     {
8180       dlc[ 7] = 7; 
8181       dlc[ 8] = 0; 
8182       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8183       dlc[10] = 0x03; /* V.42bis P0 */
8184       dlc[11] = 0;    /* V.42bis P0 */
8185       dlc[12] = 0;    /* V.42bis P1 */
8186       dlc[13] = 0;    /* V.42bis P1 */
8187       dlc[14] = 0;    /* V.42bis P2 */
8188       dlc[15] = 0;    /* V.42bis P2 */
8189     dlc[ 0] = 15;
8190     }
8191     add_p(plci, DLC, dlc);
8192   }
8193   else
8194
8195   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8196   {
8197     if (plci->B3_prot != B3_TRANSPARENT)
8198       return _B_STACK_NOT_SUPPORTED;
8199
8200     dlc[0] = 6;
8201     PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8202     dlc[3] = 0x08;
8203     dlc[4] = 0x01;
8204     dlc[5] = 127;
8205     dlc[6] = 7;
8206     if (b2_config->length != 0)
8207     {
8208       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8209         return _WRONG_MESSAGE_FORMAT;
8210       }
8211       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8212       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8213       if (b2_config->info[3] != 128)
8214       {
8215         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8216         return _B2_PARM_NOT_SUPPORTED;
8217       }
8218       dlc[5] = (byte)(b2_config->info[3] - 1);
8219       dlc[6] = b2_config->info[4];
8220       if(llc[1]==V120_V42BIS){
8221         if (b2_config->length >= 10){
8222           dlc[ 7] = 6; 
8223           dlc[ 8] = 0; 
8224           dlc[ 9] = b2_config_parms[4].info[0];
8225           dlc[10] = b2_config_parms[4].info[1];
8226           dlc[11] = b2_config_parms[5].info[0];
8227           dlc[12] = b2_config_parms[5].info[1];
8228           dlc[13] = b2_config_parms[6].info[0];
8229           dlc[14] = b2_config_parms[6].info[1];
8230           dlc[ 0] = 14;
8231           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8232           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8233           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8234         }
8235         else {
8236           dlc[ 6] = 14;
8237         }
8238       }
8239     }
8240   }
8241   else
8242   {
8243     if(b2_config->length)
8244     {
8245       dbug(1,dprintf("B2-Config"));
8246       if(llc[1]==X75_V42BIS){
8247         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8248         {
8249           return _WRONG_MESSAGE_FORMAT;
8250         }
8251       }
8252       else {
8253         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8254         {
8255           return _WRONG_MESSAGE_FORMAT;
8256         }
8257       }
8258           /* if B2 Protocol is LAPD, b2_config structure is different */
8259       if(llc[1]==6)
8260       {
8261         dlc[0] = 4;
8262         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8263         else dlc[2] = 0x01;
8264         if( (b2_config->length>=2) && (plci->B2_prot==12) )
8265         {
8266           SAPI = b2_config->info[2];    /* SAPI */
8267         }
8268         dlc[1] = SAPI;
8269         if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8270         {
8271           dlc[3] = 127;      /* Mode */
8272         }
8273         else
8274         {
8275           dlc[3] = 7;        /* Mode */
8276         }
8277    
8278         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8279         else dlc[4] = 1;
8280         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8281         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8282       }
8283       else
8284       {
8285         dlc[0] = (byte)(b2_config_parms[4].length+6);
8286         dlc[3] = b2_config->info[1];
8287         dlc[4] = b2_config->info[2];
8288         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8289           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8290           return _B2_PARM_NOT_SUPPORTED;
8291         }
8292
8293         dlc[5] = (byte)(b2_config->info[3]-1);
8294         dlc[6] = b2_config->info[4];
8295         if(dlc[6]>dlc[5]){
8296           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]));
8297           return _B2_PARM_NOT_SUPPORTED;
8298         }
8299  
8300         if(llc[1]==X75_V42BIS) {
8301           if (b2_config->length >= 10){
8302             dlc[ 7] = 6; 
8303             dlc[ 8] = 0; 
8304             dlc[ 9] = b2_config_parms[4].info[0];
8305             dlc[10] = b2_config_parms[4].info[1];
8306             dlc[11] = b2_config_parms[5].info[0];
8307             dlc[12] = b2_config_parms[5].info[1];
8308             dlc[13] = b2_config_parms[6].info[0];
8309             dlc[14] = b2_config_parms[6].info[1];
8310             dlc[ 0] = 14;
8311             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8312             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8313             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8314           }
8315           else {
8316             dlc[ 6] = 14;
8317           }
8318
8319         }
8320         else {
8321           PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8322           for(i=0; i<b2_config_parms[4].length; i++)
8323             dlc[11+i] = b2_config_parms[4].info[1+i];
8324         }
8325       }
8326     }
8327   }
8328   add_p(plci, DLC, dlc);
8329
8330   b3_config = &bp_parms[5];
8331   if(b3_config->length)
8332   {
8333     if(plci->B3_prot == 4 
8334     || plci->B3_prot == 5)
8335     {
8336       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8337       {
8338         return _WRONG_MESSAGE_FORMAT;
8339       }
8340       i = GET_WORD((byte   *)(b3_config_parms[0].info));
8341       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8342         ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8343       ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
8344       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8345       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8346         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8347       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8348       {
8349
8350         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8351           & (1L << PRIVATE_FAX_PAPER_FORMATS))
8352         {
8353           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8354             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8355             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8356         }
8357
8358  ((T30_INFO *)&nlc[1])->recording_properties =
8359    T30_RECORDING_WIDTH_ISO_A3 |
8360    (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8361    (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8362       }
8363       if(plci->B3_prot == 5)
8364       {
8365         if (i & 0x0002) /* Accept incoming fax-polling requests */
8366           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8367         if (i & 0x2000) /* Do not use MR compression */
8368           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8369         if (i & 0x4000) /* Do not use MMR compression */
8370           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8371         if (i & 0x8000) /* Do not use ECM */
8372           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8373         if (plci->fax_connect_info_length != 0)
8374         {
8375           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8376           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8377           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8378           fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8379             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8380         }
8381       }
8382       /* copy station id to NLC */
8383       for(i=0; i<20; i++)
8384       {
8385         if(i<b3_config_parms[2].length)
8386         {
8387           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8388         }
8389         else
8390         {
8391           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8392         }
8393       }
8394       ((T30_INFO *)&nlc[1])->station_id_len = 20;
8395       /* copy head line to NLC */
8396       if(b3_config_parms[3].length)
8397       {
8398
8399         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8400         if (pos != 0)
8401         {
8402           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8403             pos = 0;
8404           else
8405           {
8406             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8407             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8408             len = (byte)b3_config_parms[2].length;
8409             if (len > 20)
8410               len = 20;
8411             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8412             {
8413               for (i = 0; i < len; i++)
8414                 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8415               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8416               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8417             }
8418           }
8419         }
8420
8421         len = (byte)b3_config_parms[3].length;
8422         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8423           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8424         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8425         nlc[0] += (byte)(pos + len);
8426         for (i = 0; i < len; i++)
8427           ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
8428         }
8429       else
8430         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8431
8432       plci->nsf_control_bits = 0;
8433       if(plci->B3_prot == 5)
8434       {
8435         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8436          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8437         {
8438           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8439         }
8440         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8441          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8442         {
8443           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8444         }
8445         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8446           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8447         {
8448         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8449           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8450         {
8451           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8452           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8453             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8454           }
8455             len = nlc[0];
8456           pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8457    if (pos < plci->fax_connect_info_length)
8458    {
8459      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8460               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8461           }
8462    else
8463      nlc[++len] = 0;
8464    if (pos < plci->fax_connect_info_length)
8465    {
8466      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8467               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8468           }
8469    else
8470      nlc[++len] = 0;
8471           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8472             & (1L << PRIVATE_FAX_NONSTANDARD))
8473           {
8474      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8475      {
8476               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8477                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8478        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8479                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8480             }
8481      else
8482      {
8483               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8484               {
8485                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8486                 nlc[++len] = 0;
8487               }
8488        else
8489        {
8490                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8491                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8492          nlc[++len] = (byte)(b3_config_parms[4].length);
8493          for (i = 0; i < b3_config_parms[4].length; i++)
8494     nlc[++len] = b3_config_parms[4].info[1+i];
8495        }
8496             }
8497           }
8498             nlc[0] = len;
8499    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8500     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8501    {
8502             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8503           }
8504         }
8505       }
8506
8507       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8508       len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8509       for (i = 0; i < len; i++)
8510         plci->fax_connect_info_buffer[i] = nlc[1+i];
8511       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8512       i += ((T30_INFO *)&nlc[1])->head_line_len;
8513       while (i < nlc[0])
8514         plci->fax_connect_info_buffer[len++] = nlc[++i];
8515       plci->fax_connect_info_length = len;
8516     }
8517     else
8518     {
8519       nlc[0] = 14;
8520       if(b3_config->length!=16)
8521         return _B3_PARM_NOT_SUPPORTED;
8522       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8523       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8524         return _B3_PARM_NOT_SUPPORTED;
8525       nlc[13] = b3_config->info[13];
8526       if(GET_WORD(&b3_config->info[15])>=nlc[13])
8527         return _B3_PARM_NOT_SUPPORTED;
8528       nlc[14] = b3_config->info[15];
8529     }
8530   }
8531   else
8532   {
8533     if (plci->B3_prot == 4 
8534      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8535   }
8536   add_p(plci, NLC, nlc);
8537   return 0;
8538 }
8539
8540 /*----------------------------------------------------------------*/
8541 /*      make the same as add_b23, but only for the modem related  */
8542 /*      L2 and L3 B-Chan protocol.                                */
8543 /*                                                                */
8544 /*      Enabled L2 and L3 Configurations:                         */
8545 /*        If L1 == Modem all negotiation                          */
8546 /*          only L2 == Modem with full negotiation is allowed     */
8547 /*        If L1 == Modem async or sync                            */
8548 /*          only L2 == Transparent is allowed                     */
8549 /*        L3 == Modem or L3 == Transparent are allowed            */
8550 /*      B2 Configuration for modem:                               */
8551 /*          word : enable/disable compression, bitoptions         */
8552 /*      B3 Configuration for modem:                               */
8553 /*          empty                                                 */
8554 /*----------------------------------------------------------------*/
8555 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8556 {
8557   static byte lli[12] = {1,1};
8558   static byte llc[3] = {2,0,0};
8559   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8560     API_PARSE mdm_config[2];
8561   word i;
8562   word b2_config = 0;
8563
8564   for(i=0;i<2;i++) mdm_config[i].length = 0;
8565   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8566
8567   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8568     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8569    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8570     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8571   {
8572     return (_B_STACK_NOT_SUPPORTED);
8573   }
8574   if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8575    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8576   {
8577     return (_B_STACK_NOT_SUPPORTED);
8578   }
8579
8580   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8581   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8582
8583   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8584   {
8585     if (api_parse (&bp_parms[4].info[1],
8586                   (word)bp_parms[4].length, "w",
8587                   mdm_config))
8588     {
8589       return (_WRONG_MESSAGE_FORMAT);
8590     }
8591     b2_config = GET_WORD(mdm_config[0].info);
8592   }
8593
8594   /* OK, L2 is modem */
8595
8596   lli[0] = 1;
8597   lli[1] = 1;
8598   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8599     lli[1] |= 2;
8600   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8601     lli[1] |= 4;
8602
8603   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8604     lli[1] |= 0x10;
8605     if (plci->rx_dma_descriptor <= 0) {
8606       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8607       if (plci->rx_dma_descriptor >= 0)
8608         plci->rx_dma_descriptor++;
8609     }
8610     if (plci->rx_dma_descriptor > 0) {
8611       lli[1] |= 0x40;
8612       lli[0] = 6;
8613       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8614       lli[3] = (byte)plci->rx_dma_magic;
8615       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8616       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8617       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8618     }
8619   }
8620
8621   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8622     lli[1] |= 0x20;
8623   }
8624
8625   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8626     /*V42*/ 10 : /*V42_IN*/ 9;
8627   llc[2] = 4;                      /* pass L3 always transparent */
8628   add_p(plci, LLI, lli);
8629   add_p(plci, LLC, llc);
8630   i =  1;
8631   PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8632   i += 2;
8633   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8634   {
8635     if (bp_parms[4].length)
8636   {
8637     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8638     dlc[i++] = 3; /* Addr A */
8639     dlc[i++] = 1; /* Addr B */
8640     dlc[i++] = 7; /* modulo mode */
8641     dlc[i++] = 7; /* window size */
8642     dlc[i++] = 0; /* XID len Lo  */
8643     dlc[i++] = 0; /* XID len Hi  */
8644
8645     if (b2_config & MDM_B2_DISABLE_V42bis)
8646     {
8647       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8648     }
8649     if (b2_config & MDM_B2_DISABLE_MNP)
8650     {
8651       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8652     }
8653     if (b2_config & MDM_B2_DISABLE_TRANS)
8654     {
8655       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8656     }
8657     if (b2_config & MDM_B2_DISABLE_V42)
8658     {
8659       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8660     }
8661     if (b2_config & MDM_B2_DISABLE_COMP)
8662     {
8663       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8664     }
8665     i++;
8666   }
8667   }
8668   else
8669   {
8670     dlc[i++] = 3; /* Addr A */
8671     dlc[i++] = 1; /* Addr B */
8672     dlc[i++] = 7; /* modulo mode */
8673     dlc[i++] = 7; /* window size */
8674     dlc[i++] = 0; /* XID len Lo  */
8675     dlc[i++] = 0; /* XID len Hi  */
8676     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8677                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8678                DLC_MODEMPROT_DISABLE_V42_DETECT |
8679                DLC_MODEMPROT_DISABLE_COMPRESSION;
8680   }
8681   dlc[0] = (byte)(i - 1);
8682 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8683   add_p(plci, DLC, dlc);
8684   return (0);
8685 }
8686
8687
8688 /*------------------------------------------------------------------*/
8689 /* send a request for the signaling entity                          */
8690 /*------------------------------------------------------------------*/
8691
8692 void sig_req(PLCI   * plci, byte req, byte Id)
8693 {
8694   if(!plci) return;
8695   if(plci->adapter->adapter_disabled) return;
8696   dbug(1,dprintf("sig_req(%x)",req));
8697   if (req == REMOVE)
8698     plci->sig_remove_id = plci->Sig.Id;
8699   if(plci->req_in==plci->req_in_start) {
8700     plci->req_in +=2;
8701     plci->RBuffer[plci->req_in++] = 0;
8702   }
8703   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8704   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8705   plci->RBuffer[plci->req_in++] = req;  /* request */
8706   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8707   plci->req_in_start = plci->req_in;
8708 }
8709
8710 /*------------------------------------------------------------------*/
8711 /* send a request for the network layer entity                      */
8712 /*------------------------------------------------------------------*/
8713
8714 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8715 {
8716   if(!plci) return;
8717   if(plci->adapter->adapter_disabled) return;
8718   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8719   if (req == REMOVE)
8720   {
8721     plci->nl_remove_id = plci->NL.Id;
8722     ncci_remove (plci, 0, (byte)(ncci != 0));
8723     ncci = 0;
8724   }
8725   if(plci->req_in==plci->req_in_start) {
8726     plci->req_in +=2;
8727     plci->RBuffer[plci->req_in++] = 0;
8728   }
8729   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8730   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8731   plci->RBuffer[plci->req_in++] = req;  /* request */
8732   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8733   plci->req_in_start = plci->req_in;
8734 }
8735
8736 static void send_req(PLCI *plci)
8737 {
8738   ENTITY   * e;
8739   word l;
8740 /*  word i; */
8741
8742   if(!plci) return;
8743   if(plci->adapter->adapter_disabled) return;
8744   channel_xmit_xon (plci);
8745
8746         /* if nothing to do, return */
8747   if(plci->req_in==plci->req_out) return;
8748   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8749
8750   if(plci->nl_req || plci->sig_req) return;
8751
8752   l = GET_WORD(&plci->RBuffer[plci->req_out]);
8753   plci->req_out += 2;
8754   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8755   plci->req_out += l;
8756   if(plci->RBuffer[plci->req_out]==1)
8757   {
8758     e = &plci->NL;
8759     plci->req_out++;
8760     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8761     e->ReqCh = plci->RBuffer[plci->req_out++];
8762     if(!(e->Id & 0x1f))
8763     {
8764       e->Id = NL_ID;
8765       plci->RBuffer[plci->req_out-4] = CAI;
8766       plci->RBuffer[plci->req_out-3] = 1;
8767       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8768       plci->RBuffer[plci->req_out-1] = 0;
8769       l+=3;
8770       plci->nl_global_req = plci->nl_req;
8771     }
8772     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8773   }
8774   else
8775   {
8776     e = &plci->Sig;
8777     if(plci->RBuffer[plci->req_out])
8778       e->Id = plci->RBuffer[plci->req_out];
8779     plci->req_out++;
8780     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8781     e->ReqCh = plci->RBuffer[plci->req_out++];
8782     if(!(e->Id & 0x1f))
8783       plci->sig_global_req = plci->sig_req;
8784     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8785   }
8786   plci->XData[0].PLength = l;
8787   e->X = plci->XData;
8788   plci->adapter->request(e);
8789   dbug(1,dprintf("send_ok"));
8790 }
8791
8792 void send_data(PLCI   * plci)
8793 {
8794   DIVA_CAPI_ADAPTER   * a;
8795   DATA_B3_DESC   * data;
8796   NCCI   *ncci_ptr;
8797   word ncci;
8798
8799   if (!plci->nl_req && plci->ncci_ring_list)
8800   {
8801     a = plci->adapter;
8802     ncci = plci->ncci_ring_list;
8803     do
8804     {
8805       ncci = a->ncci_next[ncci];
8806       ncci_ptr = &(a->ncci[ncci]);
8807       if (!(a->ncci_ch[ncci]
8808          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8809       {
8810         if (ncci_ptr->data_pending)
8811         {
8812           if ((a->ncci_state[ncci] == CONNECTED)
8813            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8814            || (plci->send_disc == ncci))
8815           {
8816             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8817             if ((plci->B2_prot == B2_V120_ASYNC)
8818              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8819              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8820             {
8821               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8822               plci->NData[1].PLength = data->Length;
8823               if (data->Flags & 0x10)
8824                 plci->NData[0].P = v120_break_header;
8825               else
8826                 plci->NData[0].P = v120_default_header;
8827               plci->NData[0].PLength = 1 ;
8828               plci->NL.XNum = 2;
8829               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8830             }
8831             else
8832             {
8833               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8834               plci->NData[0].PLength = data->Length;
8835               if (data->Flags & 0x10)
8836                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8837
8838               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8839                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8840
8841               else
8842                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8843             }
8844             plci->NL.X = plci->NData;
8845             plci->NL.ReqCh = a->ncci_ch[ncci];
8846             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8847             plci->data_sent = true;
8848             plci->data_sent_ptr = data->P;
8849             a->request(&plci->NL);
8850           }
8851           else {
8852             cleanup_ncci_data (plci, ncci);
8853           }
8854         }
8855         else if (plci->send_disc == ncci)
8856         {
8857           /* dprintf("N_DISC"); */
8858           plci->NData[0].PLength = 0;
8859           plci->NL.ReqCh = a->ncci_ch[ncci];
8860           plci->NL.Req = plci->nl_req = N_DISC;
8861           a->request(&plci->NL);
8862           plci->command = _DISCONNECT_B3_R;
8863           plci->send_disc = 0;
8864         }
8865       }
8866     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8867     plci->ncci_ring_list = ncci;
8868   }
8869 }
8870
8871 static void listen_check(DIVA_CAPI_ADAPTER *a)
8872 {
8873   word i,j;
8874   PLCI   * plci;
8875   byte activnotifiedcalls = 0;
8876
8877   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8878   if (!remove_started && !a->adapter_disabled)
8879   {
8880     for(i=0;i<a->max_plci;i++)
8881     {
8882       plci = &(a->plci[i]);
8883       if(plci->notifiedcall) activnotifiedcalls++;
8884     }
8885     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8886
8887     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8888       if((j=get_plci(a))) {
8889         a->listen_active++;
8890         plci = &a->plci[j-1];
8891         plci->State = LISTENING;
8892
8893         add_p(plci,OAD,"\x01\xfd");
8894
8895         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8896
8897         add_p(plci,CAI,"\x01\xc0");
8898         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8899         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8900         add_p(plci,SHIFT|6,NULL);
8901         add_p(plci,SIN,"\x02\x00\x00");
8902         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8903         sig_req(plci,ASSIGN,DSIG_ID);
8904         send_req(plci);
8905       }
8906     }
8907   }
8908 }
8909
8910 /*------------------------------------------------------------------*/
8911 /* functions for all parameters sent in INDs                        */
8912 /*------------------------------------------------------------------*/
8913
8914 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8915 {
8916   word ploc;            /* points to current location within packet */
8917   byte w;
8918   byte wlen;
8919   byte codeset,lock;
8920   byte   * in;
8921   word i;
8922   word code;
8923   word mIEindex = 0;
8924   ploc = 0;
8925   codeset = 0;
8926   lock = 0;
8927
8928   in = plci->Sig.RBuffer->P;
8929   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8930   {                            /* element but parms array is larger      */
8931     parms[i] = (byte   *)"";
8932   }
8933   for(i=0; i<multiIEsize; i++)
8934   {
8935     parms[i] = (byte   *)"";
8936   }
8937
8938   while(ploc<plci->Sig.RBuffer->length-1) {
8939
8940         /* read information element id and length                   */
8941     w = in[ploc];
8942
8943     if(w & 0x80) {
8944 /*    w &=0xf0; removed, cannot detect congestion levels */
8945 /*    upper 4 bit masked with w==SHIFT now               */
8946       wlen = 0;
8947     }
8948     else {
8949       wlen = (byte)(in[ploc+1]+1);
8950     }
8951         /* check if length valid (not exceeding end of packet)      */
8952     if((ploc+wlen) > 270) return ;
8953     if(lock & 0x80) lock &=0x7f;
8954     else codeset = lock;
8955
8956     if((w&0xf0)==SHIFT) {
8957       codeset = in[ploc];
8958       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8959       codeset &=7;
8960       lock |=0x80;
8961     }
8962     else {
8963       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8964       else code = w;
8965       code |= (codeset<<8);
8966
8967       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8968
8969       if(i<parms_id[0]+1) {
8970         if(!multiIEsize) { /* with multiIEs use next field index,          */
8971           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8972         }
8973
8974         parms[mIEindex] = &in[ploc+1];
8975         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8976         if(parms_id[i]==OAD
8977         || parms_id[i]==CONN_NR
8978         || parms_id[i]==CAD) {
8979           if(in[ploc+2] &0x80) {
8980             in[ploc+0] = (byte)(in[ploc+1]+1);
8981             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8982             in[ploc+2] = 0x80;
8983             parms[mIEindex] = &in[ploc];
8984           }
8985         }
8986         mIEindex++;       /* effects multiIEs only */
8987       }
8988     }
8989
8990     ploc +=(wlen+1);
8991   }
8992   return ;
8993 }
8994
8995 /*------------------------------------------------------------------*/
8996 /* try to match a cip from received BC and HLC                      */
8997 /*------------------------------------------------------------------*/
8998
8999 static byte ie_compare(byte *ie1, byte *ie2)
9000 {
9001   word i;
9002   if(!ie1 || ! ie2) return false;
9003   if(!ie1[0]) return false;
9004   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9005   return true;
9006 }
9007
9008 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9009 {
9010   word i;
9011   word j;
9012
9013   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9014
9015   for(j=16;j<29 &&
9016            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9017   if(j==29) return i;
9018   return j;
9019 }
9020
9021
9022 static byte AddInfo(byte   **add_i,
9023                     byte   **fty_i,
9024                     byte   *esc_chi,
9025                     byte *facility)
9026 {
9027   byte i;
9028   byte j;
9029   byte k;
9030   byte flen;
9031   byte len=0;
9032    /* facility is a nested structure */
9033    /* FTY can be more than once      */
9034
9035         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9036   {
9037     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9038   }
9039
9040   else
9041   {
9042     add_i[0] = (byte   *)"";
9043   }
9044   if(!fty_i[0][0])
9045   {
9046     add_i[3] = (byte   *)"";
9047   }
9048   else
9049   {    /* facility array found  */
9050     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9051     {
9052       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9053       len += fty_i[i][0];
9054       len += 2;
9055       flen=fty_i[i][0];
9056       facility[j++]=0x1c; /* copy fac IE */
9057       for(k=0;k<=flen;k++,j++)
9058       {
9059         facility[j]=fty_i[i][k];
9060 /*      dbug(1,dprintf("%x ",facility[j])); */
9061       }
9062     }
9063     facility[0] = len;
9064     add_i[3] = facility;
9065   }
9066 /*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9067   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9068   len += 4;                          /* calculate length of all */
9069   return(len);
9070 }
9071
9072 /*------------------------------------------------------------------*/
9073 /* voice and codec features                                         */
9074 /*------------------------------------------------------------------*/
9075
9076 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9077 {
9078   byte voice_chi[] = "\x02\x18\x01";
9079   byte channel;
9080
9081   channel = chi[chi[0]]&0x3;
9082   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9083   voice_chi[2] = (channel) ? channel : 1;
9084   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9085   add_p(plci,ESC,voice_chi);                  /* Channel */
9086   sig_req(plci,TEL_CTRL,0);
9087   send_req(plci);
9088   if(a->AdvSignalPLCI)
9089   {
9090     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9091   }
9092 }
9093
9094 static void VoiceChannelOff(PLCI *plci)
9095 {
9096   dbug(1,dprintf("ExtDevOFF"));
9097   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9098   sig_req(plci,TEL_CTRL,0);
9099   send_req(plci);
9100   if(plci->adapter->AdvSignalPLCI)
9101   {
9102     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9103   }
9104 }
9105
9106
9107 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9108                             byte hook_listen)
9109 {
9110   word j;
9111   PLCI   *splci;
9112
9113   /* check if hardware supports handset with hook states (adv.codec) */
9114   /* or if just a on board codec is supported                        */
9115   /* the advanced codec plci is just for internal use                */
9116
9117   /* diva Pro with on-board codec:                                   */
9118   if(a->profile.Global_Options & HANDSET)
9119   {
9120     /* new call, but hook states are already signalled */
9121     if(a->AdvCodecFLAG)
9122     {
9123       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9124       {
9125         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9126         return 0x2001; /* codec in use by another application */
9127       }
9128       if(plci!=NULL)
9129       {
9130         a->AdvSignalPLCI = plci;
9131         plci->tel=ADV_VOICE;
9132       }
9133       return 0;                      /* adv codec still used */
9134     }
9135     if((j=get_plci(a)))
9136     {
9137       splci = &a->plci[j-1];
9138       splci->tel = CODEC_PERMANENT;
9139       /* hook_listen indicates if a facility_req with handset/hook support */
9140       /* was sent. Otherwise if just a call on an external device was made */
9141       /* the codec will be used but the hook info will be discarded (just  */
9142       /* the external controller is in use                                 */
9143       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9144       else
9145       {
9146         splci->State = ADVANCED_VOICE_NOSIG;
9147         if(plci)
9148         {
9149           plci->spoofed_msg = SPOOFING_REQUIRED;
9150         }
9151                                                /* indicate D-ch connect if  */
9152       }                                        /* codec is connected OK     */
9153       if(plci!=NULL)
9154       {
9155         a->AdvSignalPLCI = plci;
9156         plci->tel=ADV_VOICE;
9157       }
9158       a->AdvSignalAppl = appl;
9159       a->AdvCodecFLAG = true;
9160       a->AdvCodecPLCI = splci;
9161       add_p(splci,CAI,"\x01\x15");
9162       add_p(splci,LLI,"\x01\x00");
9163       add_p(splci,ESC,"\x02\x18\x00");
9164       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9165       splci->internal_command = PERM_COD_ASSIGN;
9166       dbug(1,dprintf("Codec Assign"));
9167       sig_req(splci,ASSIGN,DSIG_ID);
9168       send_req(splci);
9169     }
9170     else
9171     {
9172       return 0x2001; /* wrong state, no more plcis */
9173     }
9174   }
9175   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9176   {
9177     if(hook_listen) return 0x300B;               /* Facility not supported */
9178                                                  /* no hook with SCOM      */
9179     if(plci!=NULL) plci->tel = CODEC;
9180     dbug(1,dprintf("S/SCOM codec"));
9181     /* first time we use the scom-s codec we must shut down the internal   */
9182     /* handset application of the card. This can be done by an assign with */
9183     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9184     if(!a->scom_appl_disable){
9185       if((j=get_plci(a))) {
9186         splci = &a->plci[j-1];
9187         add_p(splci,CAI,"\x01\x80");
9188         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9189         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9190         send_req(splci);
9191         a->scom_appl_disable = true;
9192       }
9193       else{
9194         return 0x2001; /* wrong state, no more plcis */
9195       }
9196     }
9197   }
9198   else return 0x300B;               /* Facility not supported */
9199
9200   return 0;
9201 }
9202
9203
9204 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9205 {
9206
9207   dbug(1,dprintf("CodecIdCheck"));
9208
9209   if(a->AdvSignalPLCI == plci)
9210   {
9211     dbug(1,dprintf("PLCI owns codec"));
9212     VoiceChannelOff(a->AdvCodecPLCI);
9213     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9214     {
9215       dbug(1,dprintf("remove temp codec PLCI"));
9216       plci_remove(a->AdvCodecPLCI);
9217       a->AdvCodecFLAG  = 0;
9218       a->AdvCodecPLCI  = NULL;
9219       a->AdvSignalAppl = NULL;
9220     }
9221     a->AdvSignalPLCI = NULL;
9222   }
9223 }
9224
9225 /* -------------------------------------------------------------------
9226     Ask for physical address of card on PCI bus
9227    ------------------------------------------------------------------- */
9228 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9229                                         IDI_SYNC_REQ  * preq) {
9230   a->sdram_bar = 0;
9231   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9232     ENTITY   * e = (ENTITY   *)preq;
9233
9234     e->user[0] = a->Id - 1;
9235     preq->xdi_sdram_bar.info.bar    = 0;
9236     preq->xdi_sdram_bar.Req         = 0;
9237     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9238
9239     (*(a->request))(e);
9240
9241     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9242     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9243   }
9244 }
9245
9246 /* -------------------------------------------------------------------
9247      Ask XDI about extended features
9248    ------------------------------------------------------------------- */
9249 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9250   IDI_SYNC_REQ   * preq;
9251     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9252
9253     char features[4];
9254   preq = (IDI_SYNC_REQ   *)&buffer[0];
9255
9256   if (!diva_xdi_extended_features) {
9257     ENTITY   * e = (ENTITY   *)preq;
9258     diva_xdi_extended_features |= 0x80000000;
9259
9260     e->user[0] = a->Id - 1;
9261     preq->xdi_extended_features.Req = 0;
9262     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9263     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9264     preq->xdi_extended_features.info.features = &features[0];
9265
9266     (*(a->request))(e);
9267
9268     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9269       /*
9270          Check features located in the byte '0'
9271          */
9272       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9273         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9274       }
9275       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9276         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9277         dbug(1,dprintf("XDI provides RxDMA"));
9278       }
9279       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9280         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9281       }
9282       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9283         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9284         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9285       }
9286
9287     }
9288   }
9289
9290   diva_ask_for_xdi_sdram_bar (a, preq);
9291 }
9292
9293 /*------------------------------------------------------------------*/
9294 /* automatic law                                                    */
9295 /*------------------------------------------------------------------*/
9296 /* called from OS specific part after init time to get the Law              */
9297 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9298 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9299 {
9300   word j;
9301   PLCI   *splci;
9302
9303   if(a->automatic_law) {
9304     return;
9305   }
9306   if((j=get_plci(a))) {
9307     diva_get_extended_adapter_features (a);
9308     splci = &a->plci[j-1];
9309     a->automatic_lawPLCI = splci;
9310     a->automatic_law = 1;
9311     add_p(splci,CAI,"\x01\x80");
9312     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9313     splci->internal_command = USELAW_REQ;
9314     splci->command = 0;
9315     splci->number = 0;
9316     sig_req(splci,ASSIGN,DSIG_ID);
9317     send_req(splci);
9318   }
9319 }
9320
9321 /* called from OS specific part if an application sends an Capi20Release */
9322 word CapiRelease(word Id)
9323 {
9324   word i, j, appls_found;
9325   PLCI   *plci;
9326   APPL   *this;
9327   DIVA_CAPI_ADAPTER   *a;
9328
9329   if (!Id)
9330   {
9331     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9332     return (_WRONG_APPL_ID);
9333   }
9334
9335   this = &application[Id-1];               /* get application pointer */
9336
9337   for(i=0,appls_found=0; i<max_appl; i++)
9338   {
9339     if(application[i].Id)       /* an application has been found        */
9340     {
9341       appls_found++;
9342     }
9343   }
9344
9345   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9346   {
9347     a = &adapter[i];
9348     if (a->request)
9349     {
9350       a->Info_Mask[Id-1] = 0;
9351       a->CIP_Mask[Id-1] = 0;
9352       a->Notification_Mask[Id-1] = 0;
9353       a->codec_listen[Id-1] = NULL;
9354       a->requested_options_table[Id-1] = 0;
9355       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9356       {                                      /* with this application   */
9357         plci = &a->plci[j];
9358         if(plci->Id)                         /* if plci owns no application */
9359         {                                    /* it may be not jet connected */
9360           if(plci->State==INC_CON_PENDING
9361           || plci->State==INC_CON_ALERT)
9362           {
9363             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9364             {
9365               clear_c_ind_mask_bit (plci, (word)(Id-1));
9366               if(c_ind_mask_empty (plci))
9367               {
9368                 sig_req(plci,HANGUP,0);
9369                 send_req(plci);
9370                 plci->State = OUTG_DIS_PENDING;
9371               }
9372             }
9373           }
9374           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9375           {
9376             clear_c_ind_mask_bit (plci, (word)(Id-1));
9377             if(c_ind_mask_empty (plci))
9378             {
9379               if(!plci->appl)
9380               {
9381                 plci_remove(plci);
9382                 plci->State = IDLE;
9383               }
9384             }
9385           }
9386           if(plci->appl==this)
9387           {
9388             plci->appl = NULL;
9389             plci_remove(plci);
9390             plci->State = IDLE;
9391           }
9392         }
9393       }
9394       listen_check(a);
9395
9396       if(a->flag_dynamic_l1_down)
9397       {
9398         if(appls_found==1)            /* last application does a capi release */
9399         {
9400           if((j=get_plci(a)))
9401           {
9402             plci = &a->plci[j-1];
9403             plci->command = 0;
9404             add_p(plci,OAD,"\x01\xfd");
9405             add_p(plci,CAI,"\x01\x80");
9406             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9407             add_p(plci,SHIFT|6,NULL);
9408             add_p(plci,SIN,"\x02\x00\x00");
9409             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9410             sig_req(plci,ASSIGN,DSIG_ID);
9411             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9412             sig_req(plci,SIG_CTRL,0);
9413             send_req(plci);
9414           }
9415         }
9416       }
9417       if(a->AdvSignalAppl==this)
9418       {
9419         this->NullCREnable = false;
9420         if (a->AdvCodecPLCI)
9421         {
9422           plci_remove(a->AdvCodecPLCI);
9423           a->AdvCodecPLCI->tel = 0;
9424           a->AdvCodecPLCI->adv_nl = 0;
9425         }
9426         a->AdvSignalAppl = NULL;
9427         a->AdvSignalPLCI = NULL;
9428         a->AdvCodecFLAG = 0;
9429         a->AdvCodecPLCI = NULL;
9430       }
9431     }
9432   }
9433
9434   this->Id = 0;
9435
9436   return GOOD;
9437 }
9438
9439 static word plci_remove_check(PLCI   *plci)
9440 {
9441   if(!plci) return true;
9442   if(!plci->NL.Id && c_ind_mask_empty (plci))
9443   {
9444     if(plci->Sig.Id == 0xff)
9445       plci->Sig.Id = 0;
9446     if(!plci->Sig.Id)
9447     {
9448       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9449       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9450       if (plci->Id)
9451       {
9452         CodecIdCheck(plci->adapter, plci);
9453         clear_b1_config (plci);
9454         ncci_remove (plci, 0, false);
9455         plci_free_msg_in_queue (plci);
9456         channel_flow_control_remove (plci);
9457         plci->Id = 0;
9458         plci->State = IDLE;
9459         plci->channels = 0;
9460         plci->appl = NULL;
9461         plci->notifiedcall = 0;
9462       }
9463       listen_check(plci->adapter);
9464       return true;
9465     }
9466   }
9467   return false;
9468 }
9469
9470
9471 /*------------------------------------------------------------------*/
9472
9473 static byte plci_nl_busy (PLCI   *plci)
9474 {
9475   /* only applicable for non-multiplexed protocols */
9476   return (plci->nl_req
9477     || (plci->ncci_ring_list
9478      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9479      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9480 }
9481
9482
9483 /*------------------------------------------------------------------*/
9484 /* DTMF facilities                                                  */
9485 /*------------------------------------------------------------------*/
9486
9487
9488 static struct
9489 {
9490   byte send_mask;
9491   byte listen_mask;
9492   byte character;
9493   byte code;
9494 } dtmf_digit_map[] =
9495 {
9496   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9497   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9498   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9499   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9500   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9501   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9502   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9503   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9504   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9505   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9506   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9507   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9508   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9509   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9510   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9511   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9512   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9513   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9514   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9515   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9516
9517   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9518   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9519   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9520   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9521   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9522   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9523   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9524   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9525   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9526   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9527   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9528   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9529   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9530   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9531   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9532   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9533   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9534   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9535   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9536   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9537   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9538   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9539   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9540   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9541   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9542   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9543   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9544   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9545   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9546   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9547   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9548   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9549   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9550   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9551   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9552   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9553   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9554   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9555   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9556   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9557   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9558   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9559   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9560   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9561   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9562   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9563   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9564   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9565   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9566   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9567   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9568   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9569
9570 };
9571
9572 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9573
9574
9575 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9576 {
9577   word min_digit_duration, min_gap_duration;
9578
9579   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9580     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9581     (char   *)(FILE_), __LINE__, enable_mask));
9582
9583   if (enable_mask != 0)
9584   {
9585     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9586     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9587     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9588     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9589     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9590     plci->NData[0].PLength = 5;
9591
9592     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9593     plci->NData[0].PLength += 2;
9594     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9595
9596   }
9597   else
9598   {
9599     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9600     plci->NData[0].PLength = 1;
9601
9602     capidtmf_recv_disable (&(plci->capidtmf_state));
9603
9604   }
9605   plci->NData[0].P = plci->internal_req_buffer;
9606   plci->NL.X = plci->NData;
9607   plci->NL.ReqCh = 0;
9608   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9609   plci->adapter->request (&plci->NL);
9610 }
9611
9612
9613 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9614 {
9615   word w, i;
9616
9617   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9618     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9619     (char   *)(FILE_), __LINE__, digit_count));
9620
9621   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9622   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9623   PUT_WORD (&plci->internal_req_buffer[1], w);
9624   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9625   PUT_WORD (&plci->internal_req_buffer[3], w);
9626   for (i = 0; i < digit_count; i++)
9627   {
9628     w = 0;
9629     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9630       && (digit_buffer[i] != dtmf_digit_map[w].character))
9631     {
9632       w++;
9633     }
9634     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9635       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9636   }
9637   plci->NData[0].PLength = 5 + digit_count;
9638   plci->NData[0].P = plci->internal_req_buffer;
9639   plci->NL.X = plci->NData;
9640   plci->NL.ReqCh = 0;
9641   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9642   plci->adapter->request (&plci->NL);
9643 }
9644
9645
9646 static void dtmf_rec_clear_config (PLCI   *plci)
9647 {
9648
9649   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9650     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9651     (char   *)(FILE_), __LINE__));
9652
9653   plci->dtmf_rec_active = 0;
9654   plci->dtmf_rec_pulse_ms = 0;
9655   plci->dtmf_rec_pause_ms = 0;
9656
9657   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9658
9659 }
9660
9661
9662 static void dtmf_send_clear_config (PLCI   *plci)
9663 {
9664
9665   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9666     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9667     (char   *)(FILE_), __LINE__));
9668
9669   plci->dtmf_send_requests = 0;
9670   plci->dtmf_send_pulse_ms = 0;
9671   plci->dtmf_send_pause_ms = 0;
9672 }
9673
9674
9675 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9676 {
9677
9678   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9679     UnMapId (Id), (char   *)(FILE_), __LINE__));
9680
9681   while (plci->dtmf_send_requests != 0)
9682     dtmf_confirmation (Id, plci);
9683 }
9684
9685
9686 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9687 {
9688
9689   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9690     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9691
9692   return (GOOD);
9693 }
9694
9695
9696 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9697 {
9698   word Info;
9699
9700   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9701     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9702
9703   Info = GOOD;
9704   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9705   {
9706     switch (plci->adjust_b_state)
9707     {
9708     case ADJUST_B_RESTORE_DTMF_1:
9709       plci->internal_command = plci->adjust_b_command;
9710       if (plci_nl_busy (plci))
9711       {
9712         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9713         break;
9714       }
9715       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9716       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9717       break;
9718     case ADJUST_B_RESTORE_DTMF_2:
9719       if ((Rc != OK) && (Rc != OK_FC))
9720       {
9721         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9722           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9723         Info = _WRONG_STATE;
9724         break;
9725       }
9726       break;
9727     }
9728   }
9729   return (Info);
9730 }
9731
9732
9733 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9734 {
9735   word internal_command, Info;
9736   byte mask;
9737     byte result[4];
9738
9739   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9740     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9741     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9742     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9743
9744   Info = GOOD;
9745   result[0] = 2;
9746   PUT_WORD (&result[1], DTMF_SUCCESS);
9747   internal_command = plci->internal_command;
9748   plci->internal_command = 0;
9749   mask = 0x01;
9750   switch (plci->dtmf_cmd)
9751   {
9752
9753   case DTMF_LISTEN_TONE_START:
9754     mask <<= 1;
9755   case DTMF_LISTEN_MF_START:
9756     mask <<= 1;
9757
9758   case DTMF_LISTEN_START:
9759     switch (internal_command)
9760     {
9761     default:
9762       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9763         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9764     case DTMF_COMMAND_1:
9765       if (adjust_b_process (Id, plci, Rc) != GOOD)
9766       {
9767         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9768           UnMapId (Id), (char   *)(FILE_), __LINE__));
9769         Info = _FACILITY_NOT_SUPPORTED;
9770         break;
9771       }
9772       if (plci->internal_command)
9773         return;
9774     case DTMF_COMMAND_2:
9775       if (plci_nl_busy (plci))
9776       {
9777         plci->internal_command = DTMF_COMMAND_2;
9778         return;
9779       }
9780       plci->internal_command = DTMF_COMMAND_3;
9781       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9782       return;
9783     case DTMF_COMMAND_3:
9784       if ((Rc != OK) && (Rc != OK_FC))
9785       {
9786         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9787           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9788         Info = _FACILITY_NOT_SUPPORTED;
9789         break;
9790       }
9791
9792       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9793
9794       plci->dtmf_rec_active |= mask;
9795       break;
9796     }
9797     break;
9798
9799
9800   case DTMF_LISTEN_TONE_STOP:
9801     mask <<= 1;
9802   case DTMF_LISTEN_MF_STOP:
9803     mask <<= 1;
9804
9805   case DTMF_LISTEN_STOP:
9806     switch (internal_command)
9807     {
9808     default:
9809       plci->dtmf_rec_active &= ~mask;
9810       if (plci->dtmf_rec_active)
9811         break;
9812 /*
9813     case DTMF_COMMAND_1:
9814       if (plci->dtmf_rec_active)
9815       {
9816         if (plci_nl_busy (plci))
9817         {
9818           plci->internal_command = DTMF_COMMAND_1;
9819           return;
9820         }
9821         plci->dtmf_rec_active &= ~mask;
9822         plci->internal_command = DTMF_COMMAND_2;
9823         dtmf_enable_receiver (plci, false);
9824         return;
9825       }
9826       Rc = OK;
9827     case DTMF_COMMAND_2:
9828       if ((Rc != OK) && (Rc != OK_FC))
9829       {
9830         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9831           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9832         Info = _FACILITY_NOT_SUPPORTED;
9833         break;
9834       }
9835 */
9836       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9837         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9838     case DTMF_COMMAND_3:
9839       if (adjust_b_process (Id, plci, Rc) != GOOD)
9840       {
9841         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9842           UnMapId (Id), (char   *)(FILE_), __LINE__));
9843         Info = _FACILITY_NOT_SUPPORTED;
9844         break;
9845       }
9846       if (plci->internal_command)
9847         return;
9848       break;
9849     }
9850     break;
9851
9852
9853   case DTMF_SEND_TONE:
9854     mask <<= 1;
9855   case DTMF_SEND_MF:
9856     mask <<= 1;
9857
9858   case DTMF_DIGITS_SEND:
9859     switch (internal_command)
9860     {
9861     default:
9862       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9863         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9864         DTMF_COMMAND_1);
9865     case DTMF_COMMAND_1:
9866       if (adjust_b_process (Id, plci, Rc) != GOOD)
9867       {
9868         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9869           UnMapId (Id), (char   *)(FILE_), __LINE__));
9870         Info = _FACILITY_NOT_SUPPORTED;
9871         break;
9872       }
9873       if (plci->internal_command)
9874         return;
9875     case DTMF_COMMAND_2:
9876       if (plci_nl_busy (plci))
9877       {
9878         plci->internal_command = DTMF_COMMAND_2;
9879         return;
9880       }
9881       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9882       plci->internal_command = DTMF_COMMAND_3;
9883       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9884       return;
9885     case DTMF_COMMAND_3:
9886       if ((Rc != OK) && (Rc != OK_FC))
9887       {
9888         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9889           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9890         if (plci->dtmf_send_requests != 0)
9891           (plci->dtmf_send_requests)--;
9892         Info = _FACILITY_NOT_SUPPORTED;
9893         break;
9894       }
9895       return;
9896     }
9897     break;
9898   }
9899   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9900     "wws", Info, SELECTOR_DTMF, result);
9901 }
9902
9903
9904 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9905 {
9906   word Info;
9907   word i, j;
9908   byte mask;
9909     API_PARSE dtmf_parms[5];
9910     byte result[40];
9911
9912   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9913     UnMapId (Id), (char   *)(FILE_), __LINE__));
9914
9915   Info = GOOD;
9916   result[0] = 2;
9917   PUT_WORD (&result[1], DTMF_SUCCESS);
9918   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9919   {
9920     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9921       UnMapId (Id), (char   *)(FILE_), __LINE__));
9922     Info = _FACILITY_NOT_SUPPORTED;
9923   }
9924   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9925   {
9926     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9927       UnMapId (Id), (char   *)(FILE_), __LINE__));
9928     Info = _WRONG_MESSAGE_FORMAT;
9929   }
9930
9931   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9932     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9933   {
9934     if (!((a->requested_options_table[appl->Id-1])
9935         & (1L << PRIVATE_DTMF_TONE)))
9936     {
9937       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9938         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9939       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9940     }
9941     else
9942     {
9943       for (i = 0; i < 32; i++)
9944         result[4 + i] = 0;
9945       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9946       {
9947         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9948         {
9949           if (dtmf_digit_map[i].listen_mask != 0)
9950             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9951         }
9952       }
9953       else
9954       {
9955         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9956         {
9957           if (dtmf_digit_map[i].send_mask != 0)
9958             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9959         }
9960       }
9961       result[0] = 3 + 32;
9962       result[3] = 32;
9963     }
9964   }
9965
9966   else if (plci == NULL)
9967   {
9968     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9969       UnMapId (Id), (char   *)(FILE_), __LINE__));
9970     Info = _WRONG_IDENTIFIER;
9971   }
9972   else
9973   {
9974     if (!plci->State
9975      || !plci->NL.Id || plci->nl_remove_id)
9976     {
9977       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9978         UnMapId (Id), (char   *)(FILE_), __LINE__));
9979       Info = _WRONG_STATE;
9980     }
9981     else
9982     {
9983       plci->command = 0;
9984       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9985       mask = 0x01;
9986       switch (plci->dtmf_cmd)
9987       {
9988
9989       case DTMF_LISTEN_TONE_START:
9990       case DTMF_LISTEN_TONE_STOP:
9991         mask <<= 1;
9992       case DTMF_LISTEN_MF_START:
9993       case DTMF_LISTEN_MF_STOP:
9994         mask <<= 1;
9995         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9996           & (1L << PRIVATE_DTMF_TONE)))
9997         {
9998           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9999             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10000           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10001           break;
10002         }
10003
10004       case DTMF_LISTEN_START:
10005       case DTMF_LISTEN_STOP:
10006         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10007          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10008         {
10009           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10010             UnMapId (Id), (char   *)(FILE_), __LINE__));
10011           Info = _FACILITY_NOT_SUPPORTED;
10012           break;
10013         }
10014         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10015         {
10016           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10017           {
10018             plci->dtmf_rec_pulse_ms = 0;
10019             plci->dtmf_rec_pause_ms = 0;
10020           }
10021           else
10022           {
10023             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10024             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10025           }
10026         }
10027         start_internal_command (Id, plci, dtmf_command);
10028         return (false);
10029
10030
10031       case DTMF_SEND_TONE:
10032         mask <<= 1;
10033       case DTMF_SEND_MF:
10034         mask <<= 1;
10035         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10036           & (1L << PRIVATE_DTMF_TONE)))
10037         {
10038           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10039             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10040           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10041           break;
10042         }
10043
10044       case DTMF_DIGITS_SEND:
10045         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10046         {
10047           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10048             UnMapId (Id), (char   *)(FILE_), __LINE__));
10049           Info = _WRONG_MESSAGE_FORMAT;
10050           break;
10051         }
10052         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10053         {
10054           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10055           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10056         }
10057         i = 0;
10058         j = 0;
10059         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10060         {
10061           j = 0;
10062           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10063             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10064              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10065           {
10066             j++;
10067           }
10068           i++;
10069         }
10070         if (j == DTMF_DIGIT_MAP_ENTRIES)
10071         {
10072           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10073             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10074           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10075           break;
10076         }
10077         if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10078         {
10079           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10080             UnMapId (Id), (char   *)(FILE_), __LINE__));
10081           Info = _WRONG_STATE;
10082           break;
10083         }
10084         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10085         start_internal_command (Id, plci, dtmf_command);
10086         return (false);
10087
10088       default:
10089         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10090           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10091         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10092       }
10093     }
10094   }
10095   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10096     "wws", Info, SELECTOR_DTMF, result);
10097   return (false);
10098 }
10099
10100
10101 static void dtmf_confirmation (dword Id, PLCI   *plci)
10102 {
10103   word Info;
10104   word i;
10105     byte result[4];
10106
10107   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10108     UnMapId (Id), (char   *)(FILE_), __LINE__));
10109
10110   Info = GOOD;
10111   result[0] = 2;
10112   PUT_WORD (&result[1], DTMF_SUCCESS);
10113   if (plci->dtmf_send_requests != 0)
10114   {
10115     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10116       "wws", GOOD, SELECTOR_DTMF, result);
10117     (plci->dtmf_send_requests)--;
10118     for (i = 0; i < plci->dtmf_send_requests; i++)
10119       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10120   }
10121 }
10122
10123
10124 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10125 {
10126   word i, j, n;
10127
10128   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10129     UnMapId (Id), (char   *)(FILE_), __LINE__));
10130
10131   n = 0;
10132   for (i = 1; i < length; i++)
10133   {
10134     j = 0;
10135     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10136       && ((msg[i] != dtmf_digit_map[j].code)
10137        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10138     {
10139       j++;
10140     }
10141     if (j < DTMF_DIGIT_MAP_ENTRIES)
10142     {
10143
10144       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10145        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10146        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10147       {
10148         if (n + 1 == i)
10149         {
10150           for (i = length; i > n + 1; i--)
10151             msg[i] = msg[i - 1];
10152           length++;
10153           i++;
10154         }
10155         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10156       }
10157       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10158
10159       msg[++n] = dtmf_digit_map[j].character;
10160     }
10161   }
10162   if (n != 0)
10163   {
10164     msg[0] = (byte) n;
10165     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10166   }
10167 }
10168
10169
10170 /*------------------------------------------------------------------*/
10171 /* DTMF parameters                                                  */
10172 /*------------------------------------------------------------------*/
10173
10174 static void dtmf_parameter_write (PLCI   *plci)
10175 {
10176   word i;
10177     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10178
10179   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10180     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10181     (char   *)(FILE_), __LINE__));
10182
10183   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10184   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10185   for (i = 0; i < plci->dtmf_parameter_length; i++)
10186     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10187   add_p (plci, FTY, parameter_buffer);
10188   sig_req (plci, TEL_CTRL, 0);
10189   send_req (plci);
10190 }
10191
10192
10193 static void dtmf_parameter_clear_config (PLCI   *plci)
10194 {
10195
10196   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10197     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10198     (char   *)(FILE_), __LINE__));
10199
10200   plci->dtmf_parameter_length = 0;
10201 }
10202
10203
10204 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10205 {
10206
10207   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10208     UnMapId (Id), (char   *)(FILE_), __LINE__));
10209
10210 }
10211
10212
10213 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10214 {
10215
10216   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10217     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10218
10219   return (GOOD);
10220 }
10221
10222
10223 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10224 {
10225   word Info;
10226
10227   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10228     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10229
10230   Info = GOOD;
10231   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10232    && (plci->dtmf_parameter_length != 0))
10233   {
10234     switch (plci->adjust_b_state)
10235     {
10236     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10237       plci->internal_command = plci->adjust_b_command;
10238       if (plci->sig_req)
10239       {
10240         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10241         break;
10242       }
10243       dtmf_parameter_write (plci);
10244       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10245       break;
10246     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10247       if ((Rc != OK) && (Rc != OK_FC))
10248       {
10249         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10250           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10251         Info = _WRONG_STATE;
10252         break;
10253       }
10254       break;
10255     }
10256   }
10257   return (Info);
10258 }
10259
10260
10261 /*------------------------------------------------------------------*/
10262 /* Line interconnect facilities                                     */
10263 /*------------------------------------------------------------------*/
10264
10265
10266 LI_CONFIG   *li_config_table;
10267 word li_total_channels;
10268
10269
10270 /*------------------------------------------------------------------*/
10271 /* translate a CHI information element to a channel number          */
10272 /* returns 0xff - any channel                                       */
10273 /*         0xfe - chi wrong coding                                  */
10274 /*         0xfd - D-channel                                         */
10275 /*         0x00 - no channel                                        */
10276 /*         else channel number / PRI: timeslot                      */
10277 /* if channels is provided we accept more than one channel.         */
10278 /*------------------------------------------------------------------*/
10279
10280 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10281 {
10282   int p;
10283   int i;
10284   dword map;
10285   byte excl;
10286   byte ofs;
10287   byte ch;
10288
10289   if (pchannelmap) *pchannelmap = 0;
10290   if(!chi[0]) return 0xff;
10291   excl = 0;
10292
10293   if(chi[1] & 0x20) {
10294     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10295     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10296     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10297     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10298     if(chi[1] &0x08) excl = 0x40;
10299
10300         /* int. id present */
10301     if(chi[1] &0x40) {
10302       p=i+1;
10303       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10304       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10305     }
10306
10307         /* coding standard, Number/Map, Channel Type */
10308     p=i+1;
10309     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10310     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10311     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10312
10313         /* Number/Map */
10314     if(chi[p] &0x10) {
10315
10316         /* map */
10317       if((chi[0]-p)==4) ofs = 0;
10318       else if((chi[0]-p)==3) ofs = 1;
10319       else return 0xfe;
10320       ch = 0;
10321       map = 0;
10322       for(i=0; i<4 && p<chi[0]; i++) {
10323         p++;
10324         ch += 8;
10325         map <<= 8;
10326         if(chi[p]) {
10327           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10328           map |= chi[p];
10329         }
10330       }
10331       ch += ofs;
10332       map <<= ofs;
10333     }
10334     else {
10335
10336         /* number */
10337       p=i+1;
10338       ch = chi[p] &0x3f;
10339       if(pchannelmap) {
10340         if((byte)(chi[0]-p)>30) return 0xfe;
10341         map = 0;
10342         for(i=p; i<=chi[0]; i++) {
10343           if ((chi[i] &0x7f) > 31) return 0xfe;
10344           map |= (1L << (chi[i] &0x7f));
10345         }
10346       }
10347       else {
10348         if(p!=chi[0]) return 0xfe;
10349         if (ch > 31) return 0xfe;
10350         map = (1L << ch);
10351       }
10352       if(chi[p] &0x40) return 0xfe;
10353     }
10354     if (pchannelmap) *pchannelmap = map;
10355     else if (map != ((dword)(1L << ch))) return 0xfe;
10356     return (byte)(excl | ch);
10357   }
10358   else {  /* not PRI */
10359     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10360     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10361     if(chi[1] &0x08) excl = 0x40;
10362
10363     switch(chi[1] |0x98) {
10364     case 0x98: return 0;
10365     case 0x99:
10366       if (pchannelmap) *pchannelmap = 2;
10367       return excl |1;
10368     case 0x9a:
10369       if (pchannelmap) *pchannelmap = 4;
10370       return excl |2;
10371     case 0x9b: return 0xff;
10372     case 0x9c: return 0xfd; /* d-ch */
10373     default: return 0xfe;
10374     }
10375   }
10376 }
10377
10378
10379 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10380 {
10381   DIVA_CAPI_ADAPTER   *a;
10382   PLCI   *splci;
10383   byte old_id;
10384
10385   a = plci->adapter;
10386   old_id = plci->li_bchannel_id;
10387   if (a->li_pri)
10388   {
10389     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10390       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10391     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10392     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10393       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10394   }
10395   else
10396   {
10397     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10398     {
10399       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10400         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10401       plci->li_bchannel_id = bchannel_id & 0x03;
10402       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10403       {
10404         splci = a->AdvSignalPLCI;
10405         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10406         {
10407           if ((splci->li_bchannel_id != 0)
10408            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10409           {
10410             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10411           }
10412           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10413           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10414           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10415             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10416             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10417         }
10418       }
10419       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10420         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10421     }
10422   }
10423   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10424    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10425   {
10426     mixer_clear_config (plci);
10427   }
10428   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10429     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10430     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10431 }
10432
10433
10434 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10435 {
10436   DIVA_CAPI_ADAPTER   *a;
10437   PLCI   *splci;
10438   byte ch, old_id;
10439
10440   a = plci->adapter;
10441   old_id = plci->li_bchannel_id;
10442   ch = chi_to_channel (chi, NULL);
10443   if (!(ch & 0x80))
10444   {
10445     if (a->li_pri)
10446     {
10447       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10448         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10449       plci->li_bchannel_id = (ch & 0x1f) + 1;
10450       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10451         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10452     }
10453     else
10454     {
10455       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10456       {
10457         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10458           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10459         plci->li_bchannel_id = ch & 0x1f;
10460         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10461         {
10462           splci = a->AdvSignalPLCI;
10463           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10464           {
10465             if ((splci->li_bchannel_id != 0)
10466              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10467             {
10468               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10469             }
10470             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10471             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10472             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10473               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10474               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10475           }
10476         }
10477         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10478           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10479       }
10480     }
10481   }
10482   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10483    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10484   {
10485     mixer_clear_config (plci);
10486   }
10487   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10488     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10489     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10490 }
10491
10492
10493 #define MIXER_MAX_DUMP_CHANNELS 34
10494
10495 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10496 {
10497 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10498   word n, i, j;
10499   char *p;
10500     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10501
10502   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10503     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10504
10505   for (i = 0; i < li_total_channels; i++)
10506   {
10507     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10508     if (li_config_table[i].chflags != 0)
10509       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10510     else
10511     {
10512       for (j = 0; j < li_total_channels; j++)
10513       {
10514         if (((li_config_table[i].flag_table[j]) != 0)
10515          || ((li_config_table[j].flag_table[i]) != 0))
10516         {
10517           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10518         }
10519         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10520          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10521         {
10522           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10523         }
10524       }
10525     }
10526   }
10527   for (i = 0; i < li_total_channels; i++)
10528   {
10529     for (j = 0; j < li_total_channels; j++)
10530     {
10531       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10532       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10533         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10534     }
10535   }
10536   for (n = 0; n < li_total_channels; n++)
10537   {
10538     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10539     {
10540       for (i = 0; i < li_total_channels; i++)
10541       {
10542         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10543         {
10544           for (j = 0; j < li_total_channels; j++)
10545           {
10546             li_config_table[i].coef_table[j] |=
10547               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10548           }
10549         }
10550       }
10551     }
10552   }
10553   for (i = 0; i < li_total_channels; i++)
10554   {
10555     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10556     {
10557       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10558       for (j = 0; j < li_total_channels; j++)
10559       {
10560         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10561           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10562       }
10563       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10564         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10565     }
10566   }
10567   for (i = 0; i < li_total_channels; i++)
10568   {
10569     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10570     {
10571       for (j = 0; j < li_total_channels; j++)
10572       {
10573         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10574           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10575         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10576           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10577         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10578           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10579         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10580           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10581       }
10582       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10583       {
10584         for (j = 0; j < li_total_channels; j++)
10585         {
10586           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587           {
10588             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10589             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10590               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10591           }
10592         }
10593       }
10594       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10595       {
10596         for (j = 0; j < li_total_channels; j++)
10597         {
10598           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10599             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10600         }
10601       }
10602       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
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             for (n = 0; n < li_total_channels; n++)
10609             {
10610               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10611               {
10612                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10613                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10614                 {
10615                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10616                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10617                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10618                 }
10619                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10620                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10621               }
10622             }
10623           }
10624         }
10625       }
10626     }
10627   }
10628   for (i = 0; i < li_total_channels; i++)
10629   {
10630     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10631     {
10632       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10633         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10634       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10635         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10636       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10637         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10638       for (j = 0; j < li_total_channels; j++)
10639       {
10640         if ((li_config_table[i].flag_table[j] &
10641           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10642          || (li_config_table[j].flag_table[i] &
10643           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10644         {
10645           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10646         }
10647         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10648           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10650           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651       }
10652       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10653       {
10654         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10655         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10656       }
10657     }
10658   }
10659   for (i = 0; i < li_total_channels; i++)
10660   {
10661     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10662     {
10663       j = 0;
10664       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10665         j++;
10666       if (j < li_total_channels)
10667       {
10668         for (j = 0; j < li_total_channels; j++)
10669         {
10670           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10671           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10672             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10673         }
10674       }
10675     }
10676   }
10677   n = li_total_channels;
10678   if (n > MIXER_MAX_DUMP_CHANNELS)
10679     n = MIXER_MAX_DUMP_CHANNELS;
10680   p = hex_line;
10681   for (j = 0; j < n; j++)
10682   {
10683     if ((j & 0x7) == 0)
10684       *(p++) = ' ';
10685     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10686     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10687   }
10688   *p = '\0';
10689   dbug (1, dprintf ("[%06lx] CURRENT %s",
10690     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10691   p = hex_line;
10692   for (j = 0; j < n; j++)
10693   {
10694     if ((j & 0x7) == 0)
10695       *(p++) = ' ';
10696     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10697     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10698   }
10699   *p = '\0';
10700   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10701     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10702   p = hex_line;
10703   for (j = 0; j < n; j++)
10704   {
10705     if ((j & 0x7) == 0)
10706       *(p++) = ' ';
10707     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10708     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10709   }
10710   *p = '\0';
10711   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10712     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10713   for (i = 0; i < n; i++)
10714   {
10715     p = hex_line;
10716     for (j = 0; j < n; j++)
10717     {
10718       if ((j & 0x7) == 0)
10719         *(p++) = ' ';
10720       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10721       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10722     }
10723     *p = '\0';
10724     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10725       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10726   }
10727   for (i = 0; i < n; i++)
10728   {
10729     p = hex_line;
10730     for (j = 0; j < n; j++)
10731     {
10732       if ((j & 0x7) == 0)
10733         *(p++) = ' ';
10734       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10735       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10736     }
10737     *p = '\0';
10738     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10739       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10740   }
10741 }
10742
10743
10744 static struct
10745 {
10746   byte mask;
10747   byte line_flags;
10748 } mixer_write_prog_pri[] =
10749 {
10750   { LI_COEF_CH_CH, 0 },
10751   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10752   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10753   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10754 };
10755
10756 static struct
10757 {
10758   byte from_ch;
10759   byte to_ch;
10760   byte mask;
10761   byte xconnect_override;
10762 } mixer_write_prog_bri[] =
10763 {
10764   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10765   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10766   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10767   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10768   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10769   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10770   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10771   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10772   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10773   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10774   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10775   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10776   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10777   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10778   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10779   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10780   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10781   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10782   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10783   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10784   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10785   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10786   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10787   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10788   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10789   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10790   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10791   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10792   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10793   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10794   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10795   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10796   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10797   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10798   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10799   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10800 };
10801
10802 static byte mixer_swapped_index_bri[] =
10803 {
10804   18,  /* B      to B      */
10805   19,  /* Alt B  to B      */
10806   20,  /* PC     to B      */
10807   21,  /* Alt PC to B      */
10808   22,  /* IC     to B      */
10809   23,  /* Alt IC to B      */
10810   24,  /* B      to PC     */
10811   25,  /* Alt B  to PC     */
10812   26,  /* PC     to PC     */
10813   27,  /* Alt PC to PC     */
10814   28,  /* IC     to PC     */
10815   29,  /* Alt IC to PC     */
10816   30,  /* B      to IC     */
10817   31,  /* Alt B  to IC     */
10818   32,  /* PC     to IC     */
10819   33,  /* Alt PC to IC     */
10820   34,  /* IC     to IC     */
10821   35,  /* Alt IC to IC     */
10822   0,   /* Alt B  to Alt B  */
10823   1,   /* B      to Alt B  */
10824   2,   /* Alt PC to Alt B  */
10825   3,   /* PC     to Alt B  */
10826   4,   /* Alt IC to Alt B  */
10827   5,   /* IC     to Alt B  */
10828   6,   /* Alt B  to Alt PC */
10829   7,   /* B      to Alt PC */
10830   8,   /* Alt PC to Alt PC */
10831   9,   /* PC     to Alt PC */
10832   10,  /* Alt IC to Alt PC */
10833   11,  /* IC     to Alt PC */
10834   12,  /* Alt B  to Alt IC */
10835   13,  /* B      to Alt IC */
10836   14,  /* Alt PC to Alt IC */
10837   15,  /* PC     to Alt IC */
10838   16,  /* Alt IC to Alt IC */
10839   17   /* IC     to Alt IC */
10840 };
10841
10842 static struct
10843 {
10844   byte mask;
10845   byte from_pc;
10846   byte to_pc;
10847 } xconnect_write_prog[] =
10848 {
10849   { LI_COEF_CH_CH, false, false },
10850   { LI_COEF_CH_PC, false, true },
10851   { LI_COEF_PC_CH, true, false },
10852   { LI_COEF_PC_PC, true, true }
10853 };
10854
10855
10856 static void xconnect_query_addresses (PLCI   *plci)
10857 {
10858   DIVA_CAPI_ADAPTER   *a;
10859   word w, ch;
10860   byte   *p;
10861
10862   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10863     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10864     (char   *)(FILE_), __LINE__));
10865
10866   a = plci->adapter;
10867   if (a->li_pri && ((plci->li_bchannel_id == 0)
10868    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10869   {
10870     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10871       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10872       (char   *)(FILE_), __LINE__));
10873     return;
10874   }
10875   p = plci->internal_req_buffer;
10876   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10877   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10878   w = ch;
10879   *(p++) = (byte) w;
10880   *(p++) = (byte)(w >> 8);
10881   w = ch | XCONNECT_CHANNEL_PORT_PC;
10882   *(p++) = (byte) w;
10883   *(p++) = (byte)(w >> 8);
10884   plci->NData[0].P = plci->internal_req_buffer;
10885   plci->NData[0].PLength = p - plci->internal_req_buffer;
10886   plci->NL.X = plci->NData;
10887   plci->NL.ReqCh = 0;
10888   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10889   plci->adapter->request (&plci->NL);
10890 }
10891
10892
10893 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10894 {
10895
10896   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10897     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10898     (char   *)(FILE_), __LINE__, internal_command));
10899
10900   plci->li_write_command = internal_command;
10901   plci->li_write_channel = 0;
10902 }
10903
10904
10905 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10906 {
10907   DIVA_CAPI_ADAPTER   *a;
10908   word w, n, i, j, r, s, to_ch;
10909   dword d;
10910   byte   *p;
10911   struct xconnect_transfer_address_s   *transfer_address;
10912   byte ch_map[MIXER_CHANNELS_BRI];
10913
10914   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10915     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10916
10917   a = plci->adapter;
10918   if ((plci->li_bchannel_id == 0)
10919    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10920   {
10921     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10922       UnMapId (Id), (char   *)(FILE_), __LINE__));
10923     return (true);
10924   }
10925   i = a->li_base + (plci->li_bchannel_id - 1);
10926   j = plci->li_write_channel;
10927   p = plci->internal_req_buffer;
10928   if (j != 0)
10929   {
10930     if ((Rc != OK) && (Rc != OK_FC))
10931     {
10932       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10933         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10934       return (false);
10935     }
10936   }
10937   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10938   {
10939     r = 0;
10940     s = 0;
10941     if (j < li_total_channels)
10942     {
10943       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10944       {
10945         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10946             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10947           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10948             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10949       }
10950       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10951       while ((j < li_total_channels)
10952         && ((r == 0)
10953          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10954          || (!li_config_table[j].adapter->li_pri
10955           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10956          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10957            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10958           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10959            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10960          || ((li_config_table[j].adapter->li_base != a->li_base)
10961           && !(r & s &
10962             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10963               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10964             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10965               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10966       {
10967         j++;
10968         if (j < li_total_channels)
10969           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10970       }
10971     }
10972     if (j < li_total_channels)
10973     {
10974       plci->internal_command = plci->li_write_command;
10975       if (plci_nl_busy (plci))
10976         return (true);
10977       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10978       *(p++) = UDATA_REQUEST_XCONNECT_TO;
10979       do
10980       {
10981         if (li_config_table[j].adapter->li_base != a->li_base)
10982         {
10983           r &= s &
10984             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10985               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10986             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10987               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10988         }
10989         n = 0;
10990         do
10991         {
10992           if (r & xconnect_write_prog[n].mask)
10993           {
10994             if (xconnect_write_prog[n].from_pc)
10995               transfer_address = &(li_config_table[j].send_pc);
10996             else
10997               transfer_address = &(li_config_table[j].send_b);
10998             d = transfer_address->card_address.low;
10999             *(p++) = (byte) d;
11000             *(p++) = (byte)(d >> 8);
11001             *(p++) = (byte)(d >> 16);
11002             *(p++) = (byte)(d >> 24);
11003             d = transfer_address->card_address.high;
11004             *(p++) = (byte) d;
11005             *(p++) = (byte)(d >> 8);
11006             *(p++) = (byte)(d >> 16);
11007             *(p++) = (byte)(d >> 24);
11008             d = transfer_address->offset;
11009             *(p++) = (byte) d;
11010             *(p++) = (byte)(d >> 8);
11011             *(p++) = (byte)(d >> 16);
11012             *(p++) = (byte)(d >> 24);
11013             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11014             *(p++) = (byte) w;
11015             *(p++) = (byte)(w >> 8);
11016             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11017               (li_config_table[i].adapter->u_law ?
11018                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11019                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11020             *(p++) = (byte) w;
11021             *(p++) = (byte) 0;
11022             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11023           }
11024           n++;
11025         } while ((n < ARRAY_SIZE(xconnect_write_prog))
11026           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11027         if (n == ARRAY_SIZE(xconnect_write_prog))
11028         {
11029           do
11030           {
11031             j++;
11032             if (j < li_total_channels)
11033               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11034           } while ((j < li_total_channels)
11035             && ((r == 0)
11036              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11037              || (!li_config_table[j].adapter->li_pri
11038               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11039              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11040                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11041               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11042                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11043              || ((li_config_table[j].adapter->li_base != a->li_base)
11044               && !(r & s &
11045                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11046                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11047                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11048                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11049         }
11050       } while ((j < li_total_channels)
11051         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11052     }
11053     else if (j == li_total_channels)
11054     {
11055       plci->internal_command = plci->li_write_command;
11056       if (plci_nl_busy (plci))
11057         return (true);
11058       if (a->li_pri)
11059       {
11060         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11061         w = 0;
11062         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11063           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11064         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11065           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11066         *(p++) = (byte) w;
11067         *(p++) = (byte)(w >> 8);
11068       }
11069       else
11070       {
11071         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11072         w = 0;
11073         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11074          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11075         {
11076           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11077         }
11078         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11079           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11080         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11081           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11082         *(p++) = (byte) w;
11083         *(p++) = (byte)(w >> 8);
11084         for (j = 0; j < sizeof(ch_map); j += 2)
11085         {
11086           if (plci->li_bchannel_id == 2)
11087           {
11088             ch_map[j] = (byte)(j+1);
11089             ch_map[j+1] = (byte) j;
11090           }
11091           else
11092           {
11093             ch_map[j] = (byte) j;
11094             ch_map[j+1] = (byte)(j+1);
11095           }
11096         }
11097         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11098         {
11099           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11100           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11101           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11102           {
11103             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11104               mixer_write_prog_bri[n].xconnect_override :
11105               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11106             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11107             {
11108               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11109               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11110             }
11111           }
11112           else
11113           {
11114             *p = 0x00;
11115             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11116             {
11117               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11118               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11119                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11120             }
11121           }
11122           p++;
11123         }
11124       }
11125       j = li_total_channels + 1;
11126     }
11127   }
11128   else
11129   {
11130     if (j <= li_total_channels)
11131     {
11132       plci->internal_command = plci->li_write_command;
11133       if (plci_nl_busy (plci))
11134         return (true);
11135       if (j < a->li_base)
11136         j = a->li_base;
11137       if (a->li_pri)
11138       {
11139         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11140         w = 0;
11141         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11142           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11143         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11144           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11145         *(p++) = (byte) w;
11146         *(p++) = (byte)(w >> 8);
11147         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11148         {
11149           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11150           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11151           {
11152             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11153             if (w & mixer_write_prog_pri[n].mask)
11154             {
11155               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11156               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11157             }
11158             else
11159               *(p++) = 0x00;
11160           }
11161           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11162           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11163           {
11164             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11165             if (w & mixer_write_prog_pri[n].mask)
11166             {
11167               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11168               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11169             }
11170             else
11171               *(p++) = 0x00;
11172           }
11173         }
11174       }
11175       else
11176       {
11177         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11178         w = 0;
11179         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11180          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11181         {
11182           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11183         }
11184         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11185           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11186         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11187           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11188         *(p++) = (byte) w;
11189         *(p++) = (byte)(w >> 8);
11190         for (j = 0; j < sizeof(ch_map); j += 2)
11191         {
11192           if (plci->li_bchannel_id == 2)
11193           {
11194             ch_map[j] = (byte)(j+1);
11195             ch_map[j+1] = (byte) j;
11196           }
11197           else
11198           {
11199             ch_map[j] = (byte) j;
11200             ch_map[j+1] = (byte)(j+1);
11201           }
11202         }
11203         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11204         {
11205           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11206           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11207           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11208           {
11209             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11210             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11211             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11212           }
11213           else
11214           {
11215             *p = 0x00;
11216             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11217             {
11218               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11219               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11220                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11221             }
11222           }
11223           p++;
11224         }
11225       }
11226       j = li_total_channels + 1;
11227     }
11228   }
11229   plci->li_write_channel = j;
11230   if (p != plci->internal_req_buffer)
11231   {
11232     plci->NData[0].P = plci->internal_req_buffer;
11233     plci->NData[0].PLength = p - plci->internal_req_buffer;
11234     plci->NL.X = plci->NData;
11235     plci->NL.ReqCh = 0;
11236     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11237     plci->adapter->request (&plci->NL);
11238   }
11239   return (true);
11240 }
11241
11242
11243 static void mixer_notify_update (PLCI   *plci, byte others)
11244 {
11245   DIVA_CAPI_ADAPTER   *a;
11246   word i, w;
11247   PLCI   *notify_plci;
11248     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11249
11250   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11251     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11252     (char   *)(FILE_), __LINE__, others));
11253
11254   a = plci->adapter;
11255   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11256   {
11257     if (others)
11258       plci->li_notify_update = true;
11259     i = 0;
11260     do
11261     {
11262       notify_plci = NULL;
11263       if (others)
11264       {
11265         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11266           i++;
11267         if (i < li_total_channels)
11268           notify_plci = li_config_table[i++].plci;
11269       }
11270       else
11271       {
11272         if ((plci->li_bchannel_id != 0)
11273          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11274         {
11275           notify_plci = plci;
11276         }
11277       }
11278       if ((notify_plci != NULL)
11279        && !notify_plci->li_notify_update
11280        && (notify_plci->appl != NULL)
11281        && (notify_plci->State)
11282        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11283       {
11284         notify_plci->li_notify_update = true;
11285         ((CAPI_MSG *) msg)->header.length = 18;
11286         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11287         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11288         ((CAPI_MSG *) msg)->header.number = 0;
11289         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11290         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11291         ((CAPI_MSG *) msg)->header.ncci = 0;
11292         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11293         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11294         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11295         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11296         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11297         if (w != _QUEUE_FULL)
11298         {
11299           if (w != 0)
11300           {
11301             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11302               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11303               (char   *)(FILE_), __LINE__,
11304               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11305           }
11306           notify_plci->li_notify_update = false;
11307         }
11308       }
11309     } while (others && (notify_plci != NULL));
11310     if (others)
11311       plci->li_notify_update = false;
11312   }
11313 }
11314
11315
11316 static void mixer_clear_config (PLCI   *plci)
11317 {
11318   DIVA_CAPI_ADAPTER   *a;
11319   word i, j;
11320
11321   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11322     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11323     (char   *)(FILE_), __LINE__));
11324
11325   plci->li_notify_update = false;
11326   plci->li_plci_b_write_pos = 0;
11327   plci->li_plci_b_read_pos = 0;
11328   plci->li_plci_b_req_pos = 0;
11329   a = plci->adapter;
11330   if ((plci->li_bchannel_id != 0)
11331    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11332   {
11333     i = a->li_base + (plci->li_bchannel_id - 1);
11334     li_config_table[i].curchnl = 0;
11335     li_config_table[i].channel = 0;
11336     li_config_table[i].chflags = 0;
11337     for (j = 0; j < li_total_channels; j++)
11338     {
11339       li_config_table[j].flag_table[i] = 0;
11340       li_config_table[i].flag_table[j] = 0;
11341       li_config_table[i].coef_table[j] = 0;
11342       li_config_table[j].coef_table[i] = 0;
11343     }
11344     if (!a->li_pri)
11345     {
11346       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11347       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11348       {
11349         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11350         li_config_table[i].curchnl = 0;
11351         li_config_table[i].channel = 0;
11352         li_config_table[i].chflags = 0;
11353         for (j = 0; j < li_total_channels; j++)
11354         {
11355           li_config_table[i].flag_table[j] = 0;
11356           li_config_table[j].flag_table[i] = 0;
11357           li_config_table[i].coef_table[j] = 0;
11358           li_config_table[j].coef_table[i] = 0;
11359         }
11360         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11361         {
11362           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11363           li_config_table[i].curchnl = 0;
11364           li_config_table[i].channel = 0;
11365           li_config_table[i].chflags = 0;
11366           for (j = 0; j < li_total_channels; j++)
11367           {
11368             li_config_table[i].flag_table[j] = 0;
11369             li_config_table[j].flag_table[i] = 0;
11370             li_config_table[i].coef_table[j] = 0;
11371             li_config_table[j].coef_table[i] = 0;
11372           }
11373         }
11374       }
11375     }
11376   }
11377 }
11378
11379
11380 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11381 {
11382
11383   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11384     UnMapId (Id), (char   *)(FILE_), __LINE__));
11385
11386   do
11387   {
11388     mixer_indication_coefs_set (Id, plci);
11389   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11390 }
11391
11392
11393 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11394 {
11395   DIVA_CAPI_ADAPTER   *a;
11396   word i, j;
11397
11398   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11399     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11400
11401   a = plci->adapter;
11402   if ((plci->li_bchannel_id != 0)
11403    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11404   {
11405     i = a->li_base + (plci->li_bchannel_id - 1);
11406     for (j = 0; j < li_total_channels; j++)
11407     {
11408       li_config_table[i].coef_table[j] &= 0xf;
11409       li_config_table[j].coef_table[i] &= 0xf;
11410     }
11411     if (!a->li_pri)
11412       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11413   }
11414   return (GOOD);
11415 }
11416
11417
11418 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11419 {
11420   DIVA_CAPI_ADAPTER   *a;
11421   word Info;
11422
11423   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11424     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11425
11426   Info = GOOD;
11427   a = plci->adapter;
11428   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11429    && (plci->li_bchannel_id != 0)
11430    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11431   {
11432     switch (plci->adjust_b_state)
11433     {
11434     case ADJUST_B_RESTORE_MIXER_1:
11435       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11436       {
11437         plci->internal_command = plci->adjust_b_command;
11438         if (plci_nl_busy (plci))
11439         {
11440           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11441           break;
11442         }
11443         xconnect_query_addresses (plci);
11444         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11445         break;
11446       }
11447       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11448       Rc = OK;
11449     case ADJUST_B_RESTORE_MIXER_2:
11450     case ADJUST_B_RESTORE_MIXER_3:
11451     case ADJUST_B_RESTORE_MIXER_4:
11452       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11453       {
11454         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11455           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11456         Info = _WRONG_STATE;
11457         break;
11458       }
11459       if (Rc == OK)
11460       {
11461         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11462           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11463         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11464           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11465       }
11466       else if (Rc == 0)
11467       {
11468         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11469           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11470         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11471           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11472       }
11473       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11474       {
11475         plci->internal_command = plci->adjust_b_command;
11476         break;
11477       }
11478     case ADJUST_B_RESTORE_MIXER_5:
11479       xconnect_write_coefs (plci, plci->adjust_b_command);
11480       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11481       Rc = OK;
11482     case ADJUST_B_RESTORE_MIXER_6:
11483       if (!xconnect_write_coefs_process (Id, plci, Rc))
11484       {
11485         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11486           UnMapId (Id), (char   *)(FILE_), __LINE__));
11487         Info = _FACILITY_NOT_SUPPORTED;
11488         break;
11489       }
11490       if (plci->internal_command)
11491         break;
11492       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11493     case ADJUST_B_RESTORE_MIXER_7:
11494       break;
11495     }
11496   }
11497   return (Info);
11498 }
11499
11500
11501 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11502 {
11503   DIVA_CAPI_ADAPTER   *a;
11504   word i, internal_command, Info;
11505
11506   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11507     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11508     plci->li_cmd));
11509
11510   Info = GOOD;
11511   a = plci->adapter;
11512   internal_command = plci->internal_command;
11513   plci->internal_command = 0;
11514   switch (plci->li_cmd)
11515   {
11516   case LI_REQ_CONNECT:
11517   case LI_REQ_DISCONNECT:
11518   case LI_REQ_SILENT_UPDATE:
11519     switch (internal_command)
11520     {
11521     default:
11522       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11523       {
11524         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11525           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11526       }
11527     case MIXER_COMMAND_1:
11528       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11529       {
11530         if (adjust_b_process (Id, plci, Rc) != GOOD)
11531         {
11532           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11533             UnMapId (Id), (char   *)(FILE_), __LINE__));
11534           Info = _FACILITY_NOT_SUPPORTED;
11535           break;
11536         }
11537         if (plci->internal_command)
11538           return;
11539       }
11540       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11541       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11542        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11543         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11544          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11545       {
11546         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11547       }
11548       else
11549       {
11550         do
11551         {
11552           mixer_indication_coefs_set (Id, plci);
11553         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11554       }
11555     case MIXER_COMMAND_2:
11556       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11557        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11558         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11559          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11560       {
11561         if (!xconnect_write_coefs_process (Id, plci, Rc))
11562         {
11563           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11564             UnMapId (Id), (char   *)(FILE_), __LINE__));
11565           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11566           {
11567             do
11568             {
11569               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11570                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11571               i = (plci->li_plci_b_write_pos == 0) ?
11572                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11573             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11574               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11575           }
11576           Info = _FACILITY_NOT_SUPPORTED;
11577           break;
11578         }
11579         if (plci->internal_command)
11580           return;
11581       }
11582       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11583       {
11584         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11585           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11586       }
11587     case MIXER_COMMAND_3:
11588       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11589       {
11590         if (adjust_b_process (Id, plci, Rc) != GOOD)
11591         {
11592           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11593             UnMapId (Id), (char   *)(FILE_), __LINE__));
11594           Info = _FACILITY_NOT_SUPPORTED;
11595           break;
11596         }
11597         if (plci->internal_command)
11598           return;
11599       }
11600       break;
11601     }
11602     break;
11603   }
11604   if ((plci->li_bchannel_id == 0)
11605    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11606   {
11607     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11608       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11609   }
11610   else
11611   {
11612     i = a->li_base + (plci->li_bchannel_id - 1);
11613     li_config_table[i].curchnl = plci->li_channel_bits;
11614     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11615     {
11616       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11617       li_config_table[i].curchnl = plci->li_channel_bits;
11618       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11619       {
11620         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11621         li_config_table[i].curchnl = plci->li_channel_bits;
11622       }
11623     }
11624   }
11625 }
11626
11627
11628 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11629   dword plci_b_id, byte connect, dword li_flags)
11630 {
11631   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11632   PLCI   *plci_b;
11633   DIVA_CAPI_ADAPTER   *a_b;
11634
11635   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11636   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11637   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11638   if (!a->li_pri && (plci->tel == ADV_VOICE)
11639    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11640   {
11641     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11642     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11643       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11644   }
11645   else
11646   {
11647     ch_a_v = ch_a;
11648     ch_a_s = ch_a;
11649   }
11650   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11651   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11652    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11653   {
11654     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11655     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11656       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11657   }
11658   else
11659   {
11660     ch_b_v = ch_b;
11661     ch_b_s = ch_b;
11662   }
11663   if (connect)
11664   {
11665     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11666     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11667     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669   }
11670   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11671   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11672   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11673   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11674   if (ch_a_v == ch_b_v)
11675   {
11676     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11677     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11678   }
11679   else
11680   {
11681     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11682     {
11683       for (i = 0; i < li_total_channels; i++)
11684       {
11685         if (i != ch_a_v)
11686           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11687       }
11688     }
11689     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11690     {
11691       for (i = 0; i < li_total_channels; i++)
11692       {
11693         if (i != ch_a_s)
11694           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11695       }
11696     }
11697     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11698     {
11699       for (i = 0; i < li_total_channels; i++)
11700       {
11701         if (i != ch_a_v)
11702           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11703       }
11704     }
11705     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11706     {
11707       for (i = 0; i < li_total_channels; i++)
11708       {
11709         if (i != ch_a_s)
11710           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11711       }
11712     }
11713   }
11714   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11715   {
11716     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11717     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11718     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11719     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11720   }
11721   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11722   {
11723     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11724     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11725     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11726     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11727   }
11728   if (li_flags & LI_FLAG_MONITOR_A)
11729   {
11730     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11731     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11732   }
11733   if (li_flags & LI_FLAG_MONITOR_B)
11734   {
11735     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11736     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11737   }
11738   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11739   {
11740     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11742   }
11743   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11744   {
11745     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11746     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11747   }
11748   if (li_flags & LI_FLAG_MIX_A)
11749   {
11750     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11751     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11752   }
11753   if (li_flags & LI_FLAG_MIX_B)
11754   {
11755     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11756     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11757   }
11758   if (ch_a_v != ch_a_s)
11759   {
11760     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11761     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11762   }
11763   if (ch_b_v != ch_b_s)
11764   {
11765     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11766     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11767   }
11768 }
11769
11770
11771 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11772   dword plci_b_id, byte connect, dword li_flags)
11773 {
11774   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11775   PLCI   *plci_b;
11776   DIVA_CAPI_ADAPTER   *a_b;
11777
11778   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11779   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11780   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11781   if (!a->li_pri && (plci->tel == ADV_VOICE)
11782    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11783   {
11784     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11785     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11786       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11787   }
11788   else
11789   {
11790     ch_a_v = ch_a;
11791     ch_a_s = ch_a;
11792   }
11793   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11794   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11795    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11796   {
11797     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11798     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11799       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11800   }
11801   else
11802   {
11803     ch_b_v = ch_b;
11804     ch_b_s = ch_b;
11805   }
11806   if (connect)
11807   {
11808     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11809     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11810     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11811     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11812     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11813     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11814   }
11815   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11824   {
11825     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11826     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11827     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11828     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11829   }
11830   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11831   {
11832     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11833     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11834     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11835     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11836   }
11837   if (li_flags & LI2_FLAG_MONITOR_B)
11838   {
11839     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11840     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11841   }
11842   if (li_flags & LI2_FLAG_MIX_B)
11843   {
11844     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11845     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11846   }
11847   if (li_flags & LI2_FLAG_MONITOR_X)
11848     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11849   if (li_flags & LI2_FLAG_MIX_X)
11850     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11851   if (li_flags & LI2_FLAG_LOOP_B)
11852   {
11853     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11854     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11857   }
11858   if (li_flags & LI2_FLAG_LOOP_PC)
11859     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11860   if (li_flags & LI2_FLAG_LOOP_X)
11861     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11862   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11863     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11864   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11865     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11866   if (ch_a_v != ch_a_s)
11867   {
11868     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11869     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11870   }
11871   if (ch_b_v != ch_b_s)
11872   {
11873     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11874     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11875   }
11876 }
11877
11878
11879 static word li_check_main_plci (dword Id, PLCI   *plci)
11880 {
11881   if (plci == NULL)
11882   {
11883     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11884       UnMapId (Id), (char   *)(FILE_), __LINE__));
11885     return (_WRONG_IDENTIFIER);
11886   }
11887   if (!plci->State
11888    || !plci->NL.Id || plci->nl_remove_id
11889    || (plci->li_bchannel_id == 0))
11890   {
11891     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11892       UnMapId (Id), (char   *)(FILE_), __LINE__));
11893     return (_WRONG_STATE);
11894   }
11895   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11896   return (GOOD);
11897 }
11898
11899
11900 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11901   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11902 {
11903   byte ctlr_b;
11904   PLCI   *plci_b;
11905
11906   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11907     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11908   {
11909     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11910       UnMapId (Id), (char   *)(FILE_), __LINE__));
11911     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11912     return (NULL);
11913   }
11914   ctlr_b = 0;
11915   if ((plci_b_id & 0x7f) != 0)
11916   {
11917     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11918     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11919       ctlr_b = 0;
11920   }
11921   if ((ctlr_b == 0)
11922    || (((plci_b_id >> 8) & 0xff) == 0)
11923    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11924   {
11925     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11926       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11927     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11928     return (NULL);
11929   }
11930   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11931   if (!plci_b->State
11932    || !plci_b->NL.Id || plci_b->nl_remove_id
11933    || (plci_b->li_bchannel_id == 0))
11934   {
11935     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11936       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11937     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11938     return (NULL);
11939   }
11940   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11941   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11942     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11943    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11944     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11945   {
11946     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11947       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11948     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11949     return (NULL);
11950   }
11951   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11952     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11953   {
11954     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11955       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11956     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11957     return (NULL);
11958   }
11959   return (plci_b);
11960 }
11961
11962
11963 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11964   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11965 {
11966   byte ctlr_b;
11967   PLCI   *plci_b;
11968
11969   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11970     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11971   {
11972     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11973       UnMapId (Id), (char   *)(FILE_), __LINE__));
11974     PUT_WORD (p_result, _WRONG_STATE);
11975     return (NULL);
11976   }
11977   ctlr_b = 0;
11978   if ((plci_b_id & 0x7f) != 0)
11979   {
11980     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11981     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11982       ctlr_b = 0;
11983   }
11984   if ((ctlr_b == 0)
11985    || (((plci_b_id >> 8) & 0xff) == 0)
11986    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11987   {
11988     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11989       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11990     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11991     return (NULL);
11992   }
11993   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11994   if (!plci_b->State
11995    || !plci_b->NL.Id || plci_b->nl_remove_id
11996    || (plci_b->li_bchannel_id == 0)
11997    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11998   {
11999     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12000       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12001     PUT_WORD (p_result, _WRONG_STATE);
12002     return (NULL);
12003   }
12004   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12005     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12006    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12008   {
12009     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12010       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12011     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12012     return (NULL);
12013   }
12014   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12015     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12016   {
12017     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12018       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12019     PUT_WORD (p_result, _WRONG_STATE);
12020     return (NULL);
12021   }
12022   return (plci_b);
12023 }
12024
12025
12026 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12027 {
12028   word Info;
12029   word i;
12030   dword d, li_flags, plci_b_id;
12031   PLCI   *plci_b;
12032     API_PARSE li_parms[3];
12033     API_PARSE li_req_parms[3];
12034     API_PARSE li_participant_struct[2];
12035     API_PARSE li_participant_parms[3];
12036   word participant_parms_pos;
12037   byte result_buffer[32];
12038   byte   *result;
12039   word result_pos;
12040   word plci_b_write_pos;
12041
12042   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12043     UnMapId (Id), (char   *)(FILE_), __LINE__));
12044
12045   Info = GOOD;
12046   result = result_buffer;
12047   result_buffer[0] = 0;
12048   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12049   {
12050     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12051       UnMapId (Id), (char   *)(FILE_), __LINE__));
12052     Info = _FACILITY_NOT_SUPPORTED;
12053   }
12054   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12055   {
12056     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12057       UnMapId (Id), (char   *)(FILE_), __LINE__));
12058     Info = _WRONG_MESSAGE_FORMAT;
12059   }
12060   else
12061   {
12062     result_buffer[0] = 3;
12063     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12064     result_buffer[3] = 0;
12065     switch (GET_WORD (li_parms[0].info))
12066     {
12067     case LI_GET_SUPPORTED_SERVICES:
12068       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12069       {
12070         result_buffer[0] = 17;
12071         result_buffer[3] = 14;
12072         PUT_WORD (&result_buffer[4], GOOD);
12073         d = 0;
12074         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12075           d |= LI_CONFERENCING_SUPPORTED;
12076         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12077           d |= LI_MONITORING_SUPPORTED;
12078         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12079           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12080         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12081           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12082         PUT_DWORD (&result_buffer[6], d);
12083         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12084         {
12085           d = 0;
12086           for (i = 0; i < li_total_channels; i++)
12087           {
12088             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12089              && (li_config_table[i].adapter->li_pri
12090               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12091             {
12092               d++;
12093             }
12094           }
12095         }
12096         else
12097         {
12098           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12099         }
12100         PUT_DWORD (&result_buffer[10], d / 2);
12101         PUT_DWORD (&result_buffer[14], d);
12102       }
12103       else
12104       {
12105         result_buffer[0] = 25;
12106         result_buffer[3] = 22;
12107         PUT_WORD (&result_buffer[4], GOOD);
12108         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12109         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12110           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12111         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12112           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12113         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12114           d |= LI2_PC_LOOPING_SUPPORTED;
12115         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12116           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12117         PUT_DWORD (&result_buffer[6], d);
12118         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12119         PUT_DWORD (&result_buffer[10], d / 2);
12120         PUT_DWORD (&result_buffer[14], d - 1);
12121         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12122         {
12123           d = 0;
12124           for (i = 0; i < li_total_channels; i++)
12125           {
12126             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12127              && (li_config_table[i].adapter->li_pri
12128               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12129             {
12130               d++;
12131             }
12132           }
12133         }
12134         PUT_DWORD (&result_buffer[18], d / 2);
12135         PUT_DWORD (&result_buffer[22], d - 1);
12136       }
12137       break;
12138
12139     case LI_REQ_CONNECT:
12140       if (li_parms[1].length == 8)
12141       {
12142         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12143         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12144         {
12145           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12146             UnMapId (Id), (char   *)(FILE_), __LINE__));
12147           Info = _WRONG_MESSAGE_FORMAT;
12148           break;
12149         }
12150         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12151         li_flags = GET_DWORD (li_req_parms[1].info);
12152         Info = li_check_main_plci (Id, plci);
12153         result_buffer[0] = 9;
12154         result_buffer[3] = 6;
12155         PUT_DWORD (&result_buffer[4], plci_b_id);
12156         PUT_WORD (&result_buffer[8], GOOD);
12157         if (Info != GOOD)
12158           break;
12159         result = plci->saved_msg.info;
12160         for (i = 0; i <= result_buffer[0]; i++)
12161           result[i] = result_buffer[i];
12162         plci_b_write_pos = plci->li_plci_b_write_pos;
12163         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12164         if (plci_b == NULL)
12165           break;
12166         li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12167         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12168         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12169         plci->li_plci_b_write_pos = plci_b_write_pos;
12170       }
12171       else
12172       {
12173         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12174         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12175         {
12176           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12177             UnMapId (Id), (char   *)(FILE_), __LINE__));
12178           Info = _WRONG_MESSAGE_FORMAT;
12179           break;
12180         }
12181         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12182         Info = li_check_main_plci (Id, plci);
12183         result_buffer[0] = 7;
12184         result_buffer[3] = 4;
12185         PUT_WORD (&result_buffer[4], Info);
12186         result_buffer[6] = 0;
12187         if (Info != GOOD)
12188           break;
12189         result = plci->saved_msg.info;
12190         for (i = 0; i <= result_buffer[0]; i++)
12191           result[i] = result_buffer[i];
12192         plci_b_write_pos = plci->li_plci_b_write_pos;
12193         participant_parms_pos = 0;
12194         result_pos = 7;
12195         li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12196         while (participant_parms_pos < li_req_parms[1].length)
12197         {
12198           result[result_pos] = 6;
12199           result_pos += 7;
12200           PUT_DWORD (&result[result_pos - 6], 0);
12201           PUT_WORD (&result[result_pos - 2], GOOD);
12202           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12203             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12204           {
12205             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12206               UnMapId (Id), (char   *)(FILE_), __LINE__));
12207             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12208             break;
12209           }
12210           if (api_parse (&li_participant_struct[0].info[1],
12211             li_participant_struct[0].length, "dd", li_participant_parms))
12212           {
12213             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12214               UnMapId (Id), (char   *)(FILE_), __LINE__));
12215             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12216             break;
12217           }
12218           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12219           li_flags = GET_DWORD (li_participant_parms[1].info);
12220           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12221           if (sizeof(result) - result_pos < 7)
12222           {
12223             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12224               UnMapId (Id), (char   *)(FILE_), __LINE__));
12225             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12226             break;
12227           }
12228           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12229           if (plci_b != NULL)
12230           {
12231             li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12232             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12233               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12234               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12235             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12236           }
12237           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12238             (&li_req_parms[1].info[1]));
12239         }
12240         result[0] = (byte)(result_pos - 1);
12241         result[3] = (byte)(result_pos - 4);
12242         result[6] = (byte)(result_pos - 7);
12243         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12244         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12245          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12246         {
12247           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12248           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12249         }
12250         else
12251           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12252         plci->li_plci_b_write_pos = plci_b_write_pos;
12253       }
12254       mixer_calculate_coefs (a);
12255       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12256       mixer_notify_update (plci, true);
12257       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12258         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12259       plci->command = 0;
12260       plci->li_cmd = GET_WORD (li_parms[0].info);
12261       start_internal_command (Id, plci, mixer_command);
12262       return (false);
12263
12264     case LI_REQ_DISCONNECT:
12265       if (li_parms[1].length == 4)
12266       {
12267         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12268         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12269         {
12270           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12271             UnMapId (Id), (char   *)(FILE_), __LINE__));
12272           Info = _WRONG_MESSAGE_FORMAT;
12273           break;
12274         }
12275         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12276         Info = li_check_main_plci (Id, plci);
12277         result_buffer[0] = 9;
12278         result_buffer[3] = 6;
12279         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12280         PUT_WORD (&result_buffer[8], GOOD);
12281         if (Info != GOOD)
12282           break;
12283         result = plci->saved_msg.info;
12284         for (i = 0; i <= result_buffer[0]; i++)
12285           result[i] = result_buffer[i];
12286         plci_b_write_pos = plci->li_plci_b_write_pos;
12287         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12288         if (plci_b == NULL)
12289           break;
12290         li_update_connect (Id, a, plci, plci_b_id, false, 0);
12291         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12292         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12293         plci->li_plci_b_write_pos = plci_b_write_pos;
12294       }
12295       else
12296       {
12297         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12298         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12299         {
12300           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12301             UnMapId (Id), (char   *)(FILE_), __LINE__));
12302           Info = _WRONG_MESSAGE_FORMAT;
12303           break;
12304         }
12305         Info = li_check_main_plci (Id, plci);
12306         result_buffer[0] = 7;
12307         result_buffer[3] = 4;
12308         PUT_WORD (&result_buffer[4], Info);
12309         result_buffer[6] = 0;
12310         if (Info != GOOD)
12311           break;
12312         result = plci->saved_msg.info;
12313         for (i = 0; i <= result_buffer[0]; i++)
12314           result[i] = result_buffer[i];
12315         plci_b_write_pos = plci->li_plci_b_write_pos;
12316         participant_parms_pos = 0;
12317         result_pos = 7;
12318         while (participant_parms_pos < li_req_parms[0].length)
12319         {
12320           result[result_pos] = 6;
12321           result_pos += 7;
12322           PUT_DWORD (&result[result_pos - 6], 0);
12323           PUT_WORD (&result[result_pos - 2], GOOD);
12324           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12325             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12326           {
12327             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12328               UnMapId (Id), (char   *)(FILE_), __LINE__));
12329             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12330             break;
12331           }
12332           if (api_parse (&li_participant_struct[0].info[1],
12333             li_participant_struct[0].length, "d", li_participant_parms))
12334           {
12335             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12336               UnMapId (Id), (char   *)(FILE_), __LINE__));
12337             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12338             break;
12339           }
12340           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12341           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12342           if (sizeof(result) - result_pos < 7)
12343           {
12344             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12345               UnMapId (Id), (char   *)(FILE_), __LINE__));
12346             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12347             break;
12348           }
12349           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12350           if (plci_b != NULL)
12351           {
12352             li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12353             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12354             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12355           }
12356           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12357             (&li_req_parms[0].info[1]));
12358         }
12359         result[0] = (byte)(result_pos - 1);
12360         result[3] = (byte)(result_pos - 4);
12361         result[6] = (byte)(result_pos - 7);
12362         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12363         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12364          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12365         {
12366           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12367           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12368         }
12369         else
12370           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12371         plci->li_plci_b_write_pos = plci_b_write_pos;
12372       }
12373       mixer_calculate_coefs (a);
12374       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12375       mixer_notify_update (plci, true);
12376       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12377         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12378       plci->command = 0;
12379       plci->li_cmd = GET_WORD (li_parms[0].info);
12380       start_internal_command (Id, plci, mixer_command);
12381       return (false);
12382
12383     case LI_REQ_SILENT_UPDATE:
12384       if (!plci || !plci->State
12385        || !plci->NL.Id || plci->nl_remove_id
12386        || (plci->li_bchannel_id == 0)
12387        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12388       {
12389         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12390           UnMapId (Id), (char   *)(FILE_), __LINE__));
12391         return (false);
12392       }
12393       plci_b_write_pos = plci->li_plci_b_write_pos;
12394       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12395         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12396       {
12397         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12398           UnMapId (Id), (char   *)(FILE_), __LINE__));
12399         return (false);
12400       }
12401       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12402       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12403        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12404       {
12405         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12406         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12407       }
12408       else
12409         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12410       plci->li_plci_b_write_pos = plci_b_write_pos;
12411       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12412       plci->command = 0;
12413       plci->li_cmd = GET_WORD (li_parms[0].info);
12414       start_internal_command (Id, plci, mixer_command);
12415       return (false);
12416
12417     default:
12418       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12419         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12420       Info = _FACILITY_NOT_SUPPORTED;
12421     }
12422   }
12423   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12424     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12425   return (false);
12426 }
12427
12428
12429 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12430 {
12431   dword d;
12432   DIVA_CAPI_ADAPTER   *a;
12433     byte result[12];
12434
12435   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12436     UnMapId (Id), (char   *)(FILE_), __LINE__));
12437
12438   a = plci->adapter;
12439   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12440   {
12441     do
12442     {
12443       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12444       if (!(d & LI_PLCI_B_SKIP_FLAG))
12445       {
12446         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12447         {
12448           if (d & LI_PLCI_B_DISC_FLAG)
12449           {
12450             result[0] = 5;
12451             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12452             result[3] = 2;
12453             PUT_WORD (&result[4], _LI_USER_INITIATED);
12454           }
12455           else
12456           {
12457             result[0] = 7;
12458             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12459             result[3] = 4;
12460             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12461           }
12462         }
12463         else
12464         {
12465           if (d & LI_PLCI_B_DISC_FLAG)
12466           {
12467             result[0] = 9;
12468             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12469             result[3] = 6;
12470             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12471             PUT_WORD (&result[8], _LI_USER_INITIATED);
12472           }
12473           else
12474           {
12475             result[0] = 7;
12476             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12477             result[3] = 4;
12478             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12479           }
12480         }
12481         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12482           "ws", SELECTOR_LINE_INTERCONNECT, result);
12483       }
12484       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12485         0 : plci->li_plci_b_read_pos + 1;
12486     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12487   }
12488 }
12489
12490
12491 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12492 {
12493   word i, j, ch;
12494   struct xconnect_transfer_address_s s,   *p;
12495   DIVA_CAPI_ADAPTER   *a;
12496
12497   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12498     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12499
12500   a = plci->adapter;
12501   i = 1;
12502   for (i = 1; i < length; i += 16)
12503   {
12504     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12505     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12506     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12507     ch = msg[i+12] | (msg[i+13] << 8);
12508     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12509     if (!a->li_pri && (plci->li_bchannel_id == 2))
12510       j = 1 - j;
12511     j += a->li_base;
12512     if (ch & XCONNECT_CHANNEL_PORT_PC)
12513       p = &(li_config_table[j].send_pc);
12514     else
12515       p = &(li_config_table[j].send_b);
12516     p->card_address.low = s.card_address.low;
12517     p->card_address.high = s.card_address.high;
12518     p->offset = s.offset;
12519     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12520   }
12521   if (plci->internal_command_queue[0]
12522    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12523     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12524     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12525   {
12526     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12527     if (!plci->internal_command)
12528       next_internal_command (Id, plci);
12529   }
12530   mixer_notify_update (plci, true);
12531 }
12532
12533
12534 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12535 {
12536
12537   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12538     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12539
12540 }
12541
12542
12543 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12544 {
12545   word plci_b_write_pos;
12546
12547   plci_b_write_pos = plci->li_plci_b_write_pos;
12548   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12549     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12550   {
12551     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12552       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12553       (char   *)(FILE_), __LINE__));
12554     return (false);
12555   }
12556   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12557   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12558   plci->li_plci_b_write_pos = plci_b_write_pos;
12559   return (true);
12560 }
12561
12562
12563 static void mixer_remove (PLCI   *plci)
12564 {
12565   DIVA_CAPI_ADAPTER   *a;
12566   PLCI   *notify_plci;
12567   dword plci_b_id;
12568   word i, j;
12569
12570   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12571     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12572     (char   *)(FILE_), __LINE__));
12573
12574   a = plci->adapter;
12575   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12576   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12577   {
12578     if ((plci->li_bchannel_id != 0)
12579      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12580     {
12581       i = a->li_base + (plci->li_bchannel_id - 1);
12582       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12583       {
12584         for (j = 0; j < li_total_channels; j++)
12585         {
12586           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12587            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12588           {
12589             notify_plci = li_config_table[j].plci;
12590             if ((notify_plci != NULL)
12591              && (notify_plci != plci)
12592              && (notify_plci->appl != NULL)
12593              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12594              && (notify_plci->State)
12595              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12596             {
12597               mixer_notify_source_removed (notify_plci, plci_b_id);
12598             }
12599           }
12600         }
12601         mixer_clear_config (plci);
12602         mixer_calculate_coefs (a);
12603         mixer_notify_update (plci, true);
12604       }
12605       li_config_table[i].plci = NULL;
12606       plci->li_bchannel_id = 0;
12607     }
12608   }
12609 }
12610
12611
12612 /*------------------------------------------------------------------*/
12613 /* Echo canceller facilities                                        */
12614 /*------------------------------------------------------------------*/
12615
12616
12617 static void ec_write_parameters (PLCI   *plci)
12618 {
12619   word w;
12620     byte parameter_buffer[6];
12621
12622   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12623     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12624     (char   *)(FILE_), __LINE__));
12625
12626   parameter_buffer[0] = 5;
12627   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12628   PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12629   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12630   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12631   PUT_WORD (&parameter_buffer[4], w);
12632   add_p (plci, FTY, parameter_buffer);
12633   sig_req (plci, TEL_CTRL, 0);
12634   send_req (plci);
12635 }
12636
12637
12638 static void ec_clear_config (PLCI   *plci)
12639 {
12640
12641   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12642     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12643     (char   *)(FILE_), __LINE__));
12644
12645   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12646     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12647   plci->ec_tail_length = 0;
12648 }
12649
12650
12651 static void ec_prepare_switch (dword Id, PLCI   *plci)
12652 {
12653
12654   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12655     UnMapId (Id), (char   *)(FILE_), __LINE__));
12656
12657 }
12658
12659
12660 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12661 {
12662
12663   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12664     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12665
12666   return (GOOD);
12667 }
12668
12669
12670 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12671 {
12672   word Info;
12673
12674   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12675     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12676
12677   Info = GOOD;
12678   if (plci->B1_facilities & B1_FACILITY_EC)
12679   {
12680     switch (plci->adjust_b_state)
12681     {
12682     case ADJUST_B_RESTORE_EC_1:
12683       plci->internal_command = plci->adjust_b_command;
12684       if (plci->sig_req)
12685       {
12686         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12687         break;
12688       }
12689       ec_write_parameters (plci);
12690       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12691       break;
12692     case ADJUST_B_RESTORE_EC_2:
12693       if ((Rc != OK) && (Rc != OK_FC))
12694       {
12695         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12696           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12697         Info = _WRONG_STATE;
12698         break;
12699       }
12700       break;
12701     }
12702   }
12703   return (Info);
12704 }
12705
12706
12707 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12708 {
12709   word internal_command, Info;
12710     byte result[8];
12711
12712   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12713     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12714     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12715
12716   Info = GOOD;
12717   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12718   {
12719     result[0] = 2;
12720     PUT_WORD (&result[1], EC_SUCCESS);
12721   }
12722   else
12723   {
12724     result[0] = 5;
12725     PUT_WORD (&result[1], plci->ec_cmd);
12726     result[3] = 2;
12727     PUT_WORD (&result[4], GOOD);
12728   }
12729   internal_command = plci->internal_command;
12730   plci->internal_command = 0;
12731   switch (plci->ec_cmd)
12732   {
12733   case EC_ENABLE_OPERATION:
12734   case EC_FREEZE_COEFFICIENTS:
12735   case EC_RESUME_COEFFICIENT_UPDATE:
12736   case EC_RESET_COEFFICIENTS:
12737     switch (internal_command)
12738     {
12739     default:
12740       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12741         B1_FACILITY_EC), EC_COMMAND_1);
12742     case EC_COMMAND_1:
12743       if (adjust_b_process (Id, plci, Rc) != GOOD)
12744       {
12745         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12746           UnMapId (Id), (char   *)(FILE_), __LINE__));
12747         Info = _FACILITY_NOT_SUPPORTED;
12748         break;
12749       }
12750       if (plci->internal_command)
12751         return;
12752     case EC_COMMAND_2:
12753       if (plci->sig_req)
12754       {
12755         plci->internal_command = EC_COMMAND_2;
12756         return;
12757       }
12758       plci->internal_command = EC_COMMAND_3;
12759       ec_write_parameters (plci);
12760       return;
12761     case EC_COMMAND_3:
12762       if ((Rc != OK) && (Rc != OK_FC))
12763       {
12764         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12765           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12766         Info = _FACILITY_NOT_SUPPORTED;
12767         break;
12768       }
12769       break;
12770     }
12771     break;
12772
12773   case EC_DISABLE_OPERATION:
12774     switch (internal_command)
12775     {
12776     default:
12777     case EC_COMMAND_1:
12778       if (plci->B1_facilities & B1_FACILITY_EC)
12779       {
12780         if (plci->sig_req)
12781         {
12782           plci->internal_command = EC_COMMAND_1;
12783           return;
12784         }
12785         plci->internal_command = EC_COMMAND_2;
12786         ec_write_parameters (plci);
12787         return;
12788       }
12789       Rc = OK;
12790     case EC_COMMAND_2:
12791       if ((Rc != OK) && (Rc != OK_FC))
12792       {
12793         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12794           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12795         Info = _FACILITY_NOT_SUPPORTED;
12796         break;
12797       }
12798       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12799         ~B1_FACILITY_EC), EC_COMMAND_3);
12800     case EC_COMMAND_3:
12801       if (adjust_b_process (Id, plci, Rc) != GOOD)
12802       {
12803         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12804           UnMapId (Id), (char   *)(FILE_), __LINE__));
12805         Info = _FACILITY_NOT_SUPPORTED;
12806         break;
12807       }
12808       if (plci->internal_command)
12809         return;
12810       break;
12811     }
12812     break;
12813   }
12814   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12815     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12816     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12817 }
12818
12819
12820 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12821 {
12822   word Info;
12823   word opt;
12824     API_PARSE ec_parms[3];
12825     byte result[16];
12826
12827   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12828     UnMapId (Id), (char   *)(FILE_), __LINE__));
12829
12830   Info = GOOD;
12831   result[0] = 0;
12832   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12833   {
12834     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12835       UnMapId (Id), (char   *)(FILE_), __LINE__));
12836     Info = _FACILITY_NOT_SUPPORTED;
12837   }
12838   else
12839   {
12840     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12841     {
12842       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12843       {
12844         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12845           UnMapId (Id), (char   *)(FILE_), __LINE__));
12846         Info = _WRONG_MESSAGE_FORMAT;
12847       }
12848       else
12849       {
12850         if (plci == NULL)
12851         {
12852           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12853             UnMapId (Id), (char   *)(FILE_), __LINE__));
12854           Info = _WRONG_IDENTIFIER;
12855         }
12856         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12857         {
12858           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12859             UnMapId (Id), (char   *)(FILE_), __LINE__));
12860           Info = _WRONG_STATE;
12861         }
12862         else
12863         {
12864           plci->command = 0;
12865           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12866           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12867           result[0] = 2;
12868           PUT_WORD (&result[1], EC_SUCCESS);
12869           if (msg[1].length >= 4)
12870           {
12871             opt = GET_WORD (&ec_parms[0].info[2]);
12872             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12873               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12874             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12875               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12876             if (opt & EC_DETECT_DISABLE_TONE)
12877               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12878             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12879               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12880             if (msg[1].length >= 6)
12881             {
12882               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12883             }
12884           }
12885           switch (plci->ec_cmd)
12886           {
12887           case EC_ENABLE_OPERATION:
12888             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12889             start_internal_command (Id, plci, ec_command);
12890             return (false);
12891
12892           case EC_DISABLE_OPERATION:
12893             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12894               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12895               LEC_RESET_COEFFICIENTS;
12896             start_internal_command (Id, plci, ec_command);
12897             return (false);
12898
12899           case EC_FREEZE_COEFFICIENTS:
12900             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12901             start_internal_command (Id, plci, ec_command);
12902             return (false);
12903
12904           case EC_RESUME_COEFFICIENT_UPDATE:
12905             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12906             start_internal_command (Id, plci, ec_command);
12907             return (false);
12908
12909           case EC_RESET_COEFFICIENTS:
12910             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12911             start_internal_command (Id, plci, ec_command);
12912             return (false);
12913
12914           default:
12915             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12916               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12917             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12918           }
12919         }
12920       }
12921     }
12922     else
12923     {
12924       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12925       {
12926         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12927           UnMapId (Id), (char   *)(FILE_), __LINE__));
12928         Info = _WRONG_MESSAGE_FORMAT;
12929       }
12930       else
12931       {
12932         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12933         {
12934           result[0] = 11;
12935           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12936           result[3] = 8;
12937           PUT_WORD (&result[4], GOOD);
12938           PUT_WORD (&result[6], 0x0007);
12939           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12940           PUT_WORD (&result[10], 0);
12941         }
12942         else if (plci == NULL)
12943         {
12944           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12945             UnMapId (Id), (char   *)(FILE_), __LINE__));
12946           Info = _WRONG_IDENTIFIER;
12947         }
12948         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12949         {
12950           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12951             UnMapId (Id), (char   *)(FILE_), __LINE__));
12952           Info = _WRONG_STATE;
12953         }
12954         else
12955         {
12956           plci->command = 0;
12957           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12958           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12959           result[0] = 5;
12960           PUT_WORD (&result[1], plci->ec_cmd);
12961           result[3] = 2;
12962           PUT_WORD (&result[4], GOOD);
12963           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12964             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12965           plci->ec_tail_length = 0;
12966           if (ec_parms[1].length >= 2)
12967           {
12968             opt = GET_WORD (&ec_parms[1].info[1]);
12969             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12970               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12971             if (opt & EC_DETECT_DISABLE_TONE)
12972               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12973             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12974               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12975             if (ec_parms[1].length >= 4)
12976             {
12977               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12978             }
12979           }
12980           switch (plci->ec_cmd)
12981           {
12982           case EC_ENABLE_OPERATION:
12983             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12984             start_internal_command (Id, plci, ec_command);
12985             return (false);
12986
12987           case EC_DISABLE_OPERATION:
12988             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12989               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12990               LEC_RESET_COEFFICIENTS;
12991             start_internal_command (Id, plci, ec_command);
12992             return (false);
12993
12994           default:
12995             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12996               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12997             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12998           }
12999         }
13000       }
13001     }
13002   }
13003   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13004     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13005     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13006   return (false);
13007 }
13008
13009
13010 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13011 {
13012     byte result[8];
13013
13014   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13015     UnMapId (Id), (char   *)(FILE_), __LINE__));
13016
13017   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13018   {
13019     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13020     {
13021       result[0] = 2;
13022       PUT_WORD (&result[1], 0);
13023       switch (msg[1])
13024       {
13025       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13026         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13027         break;
13028       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13029         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13030         break;
13031       case LEC_DISABLE_RELEASED:
13032         PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13033         break;
13034       }
13035     }
13036     else
13037     {
13038       result[0] = 5;
13039       PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13040       result[3] = 2;
13041       PUT_WORD (&result[4], 0);
13042       switch (msg[1])
13043       {
13044       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13046         break;
13047       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13049         break;
13050       case LEC_DISABLE_RELEASED:
13051         PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13052         break;
13053       }
13054     }
13055     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13056       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13057   }
13058 }
13059
13060
13061
13062 /*------------------------------------------------------------------*/
13063 /* Advanced voice                                                   */
13064 /*------------------------------------------------------------------*/
13065
13066 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13067 {
13068   DIVA_CAPI_ADAPTER   *a;
13069   word i;
13070   byte *p;
13071
13072   word w, n, j, k;
13073   byte ch_map[MIXER_CHANNELS_BRI];
13074
13075     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13076
13077   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13078     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13079     (char   *)(FILE_), __LINE__, write_command));
13080
13081   a = plci->adapter;
13082   p = coef_buffer + 1;
13083   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13084   i = 0;
13085   while (i + sizeof(word) <= a->adv_voice_coef_length)
13086   {
13087     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13088     p += 2;
13089     i += 2;
13090   }
13091   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13092   {
13093     PUT_WORD (p, 0x8000);
13094     p += 2;
13095     i += 2;
13096   }
13097
13098   if (!a->li_pri && (plci->li_bchannel_id == 0))
13099   {
13100     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13101     {
13102       plci->li_bchannel_id = 1;
13103       li_config_table[a->li_base].plci = plci;
13104       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13105         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13106         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13107     }
13108     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13109     {
13110       plci->li_bchannel_id = 2;
13111       li_config_table[a->li_base + 1].plci = plci;
13112       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13114         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13115     }
13116   }
13117   if (!a->li_pri && (plci->li_bchannel_id != 0)
13118    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13119   {
13120     i = a->li_base + (plci->li_bchannel_id - 1);
13121     switch (write_command)
13122     {
13123     case ADV_VOICE_WRITE_ACTIVATION:
13124       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13125       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13126       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13127       {
13128         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13129         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13130       }
13131       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13132       {
13133         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13134         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13135         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13136         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13137       }
13138       mixer_calculate_coefs (a);
13139       li_config_table[i].curchnl = li_config_table[i].channel;
13140       li_config_table[j].curchnl = li_config_table[j].channel;
13141       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13142         li_config_table[k].curchnl = li_config_table[k].channel;
13143       break;
13144
13145     case ADV_VOICE_WRITE_DEACTIVATION:
13146       for (j = 0; j < li_total_channels; j++)
13147       {
13148         li_config_table[i].flag_table[j] = 0;
13149         li_config_table[j].flag_table[i] = 0;
13150       }
13151       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13152       for (j = 0; j < li_total_channels; j++)
13153       {
13154         li_config_table[k].flag_table[j] = 0;
13155         li_config_table[j].flag_table[k] = 0;
13156       }
13157       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13158       {
13159         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13160         for (j = 0; j < li_total_channels; j++)
13161         {
13162           li_config_table[k].flag_table[j] = 0;
13163           li_config_table[j].flag_table[k] = 0;
13164         }
13165       }
13166       mixer_calculate_coefs (a);
13167       break;
13168     }
13169     if (plci->B1_facilities & B1_FACILITY_MIXER)
13170     {
13171       w = 0;
13172       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13173         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13174       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13175         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13176       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13177         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13178       *(p++) = (byte) w;
13179       *(p++) = (byte)(w >> 8);
13180       for (j = 0; j < sizeof(ch_map); j += 2)
13181       {
13182         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13183         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13184       }
13185       for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13186       {
13187         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13188         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13189         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13190         {
13191           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13192           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13193           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13194         }
13195         else
13196         {
13197           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13198             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13199         }
13200       }
13201     }
13202     else
13203     {
13204       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13205         *(p++) = a->adv_voice_coef_buffer[i];
13206     }
13207   }
13208   else
13209
13210   {
13211     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212       *(p++) = a->adv_voice_coef_buffer[i];
13213   }
13214   coef_buffer[0] = (p - coef_buffer) - 1;
13215   add_p (plci, FTY, coef_buffer);
13216   sig_req (plci, TEL_CTRL, 0);
13217   send_req (plci);
13218 }
13219
13220
13221 static void adv_voice_clear_config (PLCI   *plci)
13222 {
13223   DIVA_CAPI_ADAPTER   *a;
13224
13225   word i, j;
13226
13227
13228   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13229     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13230     (char   *)(FILE_), __LINE__));
13231
13232   a = plci->adapter;
13233   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13234   {
13235     a->adv_voice_coef_length = 0;
13236
13237     if (!a->li_pri && (plci->li_bchannel_id != 0)
13238      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13239     {
13240       i = a->li_base + (plci->li_bchannel_id - 1);
13241       li_config_table[i].curchnl = 0;
13242       li_config_table[i].channel = 0;
13243       li_config_table[i].chflags = 0;
13244       for (j = 0; j < li_total_channels; j++)
13245       {
13246         li_config_table[i].flag_table[j] = 0;
13247         li_config_table[j].flag_table[i] = 0;
13248         li_config_table[i].coef_table[j] = 0;
13249         li_config_table[j].coef_table[i] = 0;
13250       }
13251       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13252       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13253       li_config_table[i].curchnl = 0;
13254       li_config_table[i].channel = 0;
13255       li_config_table[i].chflags = 0;
13256       for (j = 0; j < li_total_channels; j++)
13257       {
13258         li_config_table[i].flag_table[j] = 0;
13259         li_config_table[j].flag_table[i] = 0;
13260         li_config_table[i].coef_table[j] = 0;
13261         li_config_table[j].coef_table[i] = 0;
13262       }
13263       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13264       {
13265         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13266         li_config_table[i].curchnl = 0;
13267         li_config_table[i].channel = 0;
13268         li_config_table[i].chflags = 0;
13269         for (j = 0; j < li_total_channels; j++)
13270         {
13271           li_config_table[i].flag_table[j] = 0;
13272           li_config_table[j].flag_table[i] = 0;
13273           li_config_table[i].coef_table[j] = 0;
13274           li_config_table[j].coef_table[i] = 0;
13275         }
13276       }
13277     }
13278
13279   }
13280 }
13281
13282
13283 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13284 {
13285
13286   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13287     UnMapId (Id), (char   *)(FILE_), __LINE__));
13288
13289 }
13290
13291
13292 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13293 {
13294
13295   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13296     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13297
13298   return (GOOD);
13299 }
13300
13301
13302 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13303 {
13304   DIVA_CAPI_ADAPTER   *a;
13305   word Info;
13306
13307   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13308     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13309
13310   Info = GOOD;
13311   a = plci->adapter;
13312   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13313    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13314   {
13315     switch (plci->adjust_b_state)
13316     {
13317     case ADJUST_B_RESTORE_VOICE_1:
13318       plci->internal_command = plci->adjust_b_command;
13319       if (plci->sig_req)
13320       {
13321         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13322         break;
13323       }
13324       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13325       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13326       break;
13327     case ADJUST_B_RESTORE_VOICE_2:
13328       if ((Rc != OK) && (Rc != OK_FC))
13329       {
13330         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13331           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13332         Info = _WRONG_STATE;
13333         break;
13334       }
13335       break;
13336     }
13337   }
13338   return (Info);
13339 }
13340
13341
13342
13343
13344 /*------------------------------------------------------------------*/
13345 /* B1 resource switching                                            */
13346 /*------------------------------------------------------------------*/
13347
13348 static byte b1_facilities_table[] =
13349 {
13350   0x00,  /* 0  No bchannel resources      */
13351   0x00,  /* 1  Codec (automatic law)      */
13352   0x00,  /* 2  Codec (A-law)              */
13353   0x00,  /* 3  Codec (y-law)              */
13354   0x00,  /* 4  HDLC for X.21              */
13355   0x00,  /* 5  HDLC                       */
13356   0x00,  /* 6  External Device 0          */
13357   0x00,  /* 7  External Device 1          */
13358   0x00,  /* 8  HDLC 56k                   */
13359   0x00,  /* 9  Transparent                */
13360   0x00,  /* 10 Loopback to network        */
13361   0x00,  /* 11 Test pattern to net        */
13362   0x00,  /* 12 Rate adaptation sync       */
13363   0x00,  /* 13 Rate adaptation async      */
13364   0x00,  /* 14 R-Interface                */
13365   0x00,  /* 15 HDLC 128k leased line      */
13366   0x00,  /* 16 FAX                        */
13367   0x00,  /* 17 Modem async                */
13368   0x00,  /* 18 Modem sync HDLC            */
13369   0x00,  /* 19 V.110 async HDLC           */
13370   0x12,  /* 20 Adv voice (Trans,mixer)    */
13371   0x00,  /* 21 Codec connected to IC      */
13372   0x0c,  /* 22 Trans,DTMF                 */
13373   0x1e,  /* 23 Trans,DTMF+mixer           */
13374   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13375   0x13,  /* 25 Trans,mixer+local          */
13376   0x12,  /* 26 HDLC,mixer                 */
13377   0x12,  /* 27 HDLC 56k,mixer             */
13378   0x2c,  /* 28 Trans,LEC+DTMF             */
13379   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13380   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13381   0x2c,  /* 31 RTP,LEC+DTMF               */
13382   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13383   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13384   0x00,  /* 34 Signaling task             */
13385   0x00,  /* 35 PIAFS                      */
13386   0x0c,  /* 36 Trans,DTMF+TONE            */
13387   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13388   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13389 };
13390
13391
13392 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13393 {
13394   word b1_facilities;
13395
13396   b1_facilities = b1_facilities_table[b1_resource];
13397   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13398   {
13399
13400     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13401        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13402
13403     {
13404       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13405         b1_facilities |= B1_FACILITY_DTMFX;
13406       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13407         b1_facilities |= B1_FACILITY_DTMFR;
13408     }
13409   }
13410   if ((b1_resource == 17) || (b1_resource == 18))
13411   {
13412     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13413       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13414   }
13415 /*
13416   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13417     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13418     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13419 */
13420   return (b1_facilities);
13421 }
13422
13423
13424 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13425 {
13426   byte b;
13427
13428   switch (b1_resource)
13429   {
13430   case 5:
13431   case 26:
13432     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13433       b = 26;
13434     else
13435       b = 5;
13436     break;
13437
13438   case 8:
13439   case 27:
13440     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13441       b = 27;
13442     else
13443       b = 8;
13444     break;
13445
13446   case 9:
13447   case 20:
13448   case 22:
13449   case 23:
13450   case 24:
13451   case 25:
13452   case 28:
13453   case 29:
13454   case 30:
13455   case 36:
13456   case 37:
13457   case 38:
13458     if (b1_facilities & B1_FACILITY_EC)
13459     {
13460       if (b1_facilities & B1_FACILITY_LOCAL)
13461         b = 30;
13462       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13463         b = 29;
13464       else
13465         b = 28;
13466     }
13467
13468     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13469       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13470        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13471     {
13472       if (b1_facilities & B1_FACILITY_LOCAL)
13473         b = 38;
13474       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13475         b = 37;
13476       else
13477         b = 36;
13478     }
13479
13480     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13481       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13482      || ((b1_facilities & B1_FACILITY_DTMFR)
13483       && ((b1_facilities & B1_FACILITY_MIXER)
13484        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13485      || ((b1_facilities & B1_FACILITY_DTMFX)
13486       && ((b1_facilities & B1_FACILITY_MIXER)
13487        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13488     {
13489       if (b1_facilities & B1_FACILITY_LOCAL)
13490         b = 24;
13491       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13492         b = 23;
13493       else
13494         b = 22;
13495     }
13496     else
13497     {
13498       if (b1_facilities & B1_FACILITY_LOCAL)
13499         b = 25;
13500       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13501         b = 20;
13502       else
13503         b = 9;
13504     }
13505     break;
13506
13507   case 31:
13508   case 32:
13509   case 33:
13510     if (b1_facilities & B1_FACILITY_LOCAL)
13511       b = 33;
13512     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13513       b = 32;
13514     else
13515       b = 31;
13516     break;
13517
13518   default:
13519     b = b1_resource;
13520   }
13521   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13522     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13523     (char   *)(FILE_), __LINE__,
13524     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13525   return (b);
13526 }
13527
13528
13529 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13530 {
13531   word removed_facilities;
13532
13533   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13534     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13535     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13536     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13537
13538   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13539   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13540
13541   if (removed_facilities & B1_FACILITY_EC)
13542     ec_clear_config (plci);
13543
13544
13545   if (removed_facilities & B1_FACILITY_DTMFR)
13546   {
13547     dtmf_rec_clear_config (plci);
13548     dtmf_parameter_clear_config (plci);
13549   }
13550   if (removed_facilities & B1_FACILITY_DTMFX)
13551     dtmf_send_clear_config (plci);
13552
13553
13554   if (removed_facilities & B1_FACILITY_MIXER)
13555     mixer_clear_config (plci);
13556
13557   if (removed_facilities & B1_FACILITY_VOICE)
13558     adv_voice_clear_config (plci);
13559   plci->B1_facilities = new_b1_facilities;
13560 }
13561
13562
13563 static void adjust_b_clear (PLCI   *plci)
13564 {
13565
13566   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13567     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13568     (char   *)(FILE_), __LINE__));
13569
13570   plci->adjust_b_restore = false;
13571 }
13572
13573
13574 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13575 {
13576   word Info;
13577   byte b1_resource;
13578   NCCI   * ncci_ptr;
13579     API_PARSE bp[2];
13580
13581   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13582     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13583
13584   Info = GOOD;
13585   switch (plci->adjust_b_state)
13586   {
13587   case ADJUST_B_START:
13588     if ((plci->adjust_b_parms_msg == NULL)
13589      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13590      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13591       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13592     {
13593       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13594         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13595       if (b1_resource == plci->B1_resource)
13596       {
13597         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13598         break;
13599       }
13600       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13601       {
13602         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13603           UnMapId (Id), (char   *)(FILE_), __LINE__,
13604           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13605         Info = _WRONG_STATE;
13606         break;
13607       }
13608     }
13609     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13610     {
13611
13612       mixer_prepare_switch (Id, plci);
13613
13614
13615       dtmf_prepare_switch (Id, plci);
13616       dtmf_parameter_prepare_switch (Id, plci);
13617
13618
13619       ec_prepare_switch (Id, plci);
13620
13621       adv_voice_prepare_switch (Id, plci);
13622     }
13623     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13624     Rc = OK;
13625   case ADJUST_B_SAVE_MIXER_1:
13626     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13627     {
13628
13629       Info = mixer_save_config (Id, plci, Rc);
13630       if ((Info != GOOD) || plci->internal_command)
13631         break;
13632
13633     }
13634     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13635     Rc = OK;
13636   case ADJUST_B_SAVE_DTMF_1:
13637     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13638     {
13639
13640       Info = dtmf_save_config (Id, plci, Rc);
13641       if ((Info != GOOD) || plci->internal_command)
13642         break;
13643
13644     }
13645     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13646   case ADJUST_B_REMOVE_L23_1:
13647     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13648      && plci->NL.Id && !plci->nl_remove_id)
13649     {
13650       plci->internal_command = plci->adjust_b_command;
13651       if (plci->adjust_b_ncci != 0)
13652       {
13653         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13654         while (ncci_ptr->data_pending)
13655         {
13656           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13657           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13658         }
13659         while (ncci_ptr->data_ack_pending)
13660           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13661       }
13662       nl_req_ncci (plci, REMOVE,
13663         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13664       send_req (plci);
13665       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13666       break;
13667     }
13668     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13669     Rc = OK;
13670   case ADJUST_B_REMOVE_L23_2:
13671     if ((Rc != OK) && (Rc != OK_FC))
13672     {
13673       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13674         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13675       Info = _WRONG_STATE;
13676       break;
13677     }
13678     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13679     {
13680       if (plci_nl_busy (plci))
13681       {
13682         plci->internal_command = plci->adjust_b_command;
13683         break;
13684       }
13685     }
13686     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13687     Rc = OK;
13688   case ADJUST_B_SAVE_EC_1:
13689     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13690     {
13691
13692       Info = ec_save_config (Id, plci, Rc);
13693       if ((Info != GOOD) || plci->internal_command)
13694         break;
13695
13696     }
13697     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13698     Rc = OK;
13699   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13700     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13701     {
13702
13703       Info = dtmf_parameter_save_config (Id, plci, Rc);
13704       if ((Info != GOOD) || plci->internal_command)
13705         break;
13706
13707     }
13708     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13709     Rc = OK;
13710   case ADJUST_B_SAVE_VOICE_1:
13711     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13712     {
13713       Info = adv_voice_save_config (Id, plci, Rc);
13714       if ((Info != GOOD) || plci->internal_command)
13715         break;
13716     }
13717     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13718   case ADJUST_B_SWITCH_L1_1:
13719     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13720     {
13721       if (plci->sig_req)
13722       {
13723         plci->internal_command = plci->adjust_b_command;
13724         break;
13725       }
13726       if (plci->adjust_b_parms_msg != NULL)
13727         api_load_msg (plci->adjust_b_parms_msg, bp);
13728       else
13729         api_load_msg (&plci->B_protocol, bp);
13730       Info = add_b1 (plci, bp,
13731         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13732         plci->adjust_b_facilities);
13733       if (Info != GOOD)
13734       {
13735         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13736           UnMapId (Id), (char   *)(FILE_), __LINE__,
13737           plci->B1_resource, plci->adjust_b_facilities));
13738         break;
13739       }
13740       plci->internal_command = plci->adjust_b_command;
13741       sig_req (plci, RESOURCES, 0);
13742       send_req (plci);
13743       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13744       break;
13745     }
13746     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13747     Rc = OK;
13748   case ADJUST_B_SWITCH_L1_2:
13749     if ((Rc != OK) && (Rc != OK_FC))
13750     {
13751       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13752         UnMapId (Id), (char   *)(FILE_), __LINE__,
13753         Rc, plci->B1_resource, plci->adjust_b_facilities));
13754       Info = _WRONG_STATE;
13755       break;
13756     }
13757     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13758     Rc = OK;
13759   case ADJUST_B_RESTORE_VOICE_1:
13760   case ADJUST_B_RESTORE_VOICE_2:
13761     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13762     {
13763       Info = adv_voice_restore_config (Id, plci, Rc);
13764       if ((Info != GOOD) || plci->internal_command)
13765         break;
13766     }
13767     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13768     Rc = OK;
13769   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13770   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13771     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13772     {
13773
13774       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13775       if ((Info != GOOD) || plci->internal_command)
13776         break;
13777
13778     }
13779     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13780     Rc = OK;
13781   case ADJUST_B_RESTORE_EC_1:
13782   case ADJUST_B_RESTORE_EC_2:
13783     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13784     {
13785
13786       Info = ec_restore_config (Id, plci, Rc);
13787       if ((Info != GOOD) || plci->internal_command)
13788         break;
13789
13790     }
13791     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13792   case ADJUST_B_ASSIGN_L23_1:
13793     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13794     {
13795       if (plci_nl_busy (plci))
13796       {
13797         plci->internal_command = plci->adjust_b_command;
13798         break;
13799       }
13800       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13801         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13802       if (plci->adjust_b_parms_msg != NULL)
13803         api_load_msg (plci->adjust_b_parms_msg, bp);
13804       else
13805         api_load_msg (&plci->B_protocol, bp);
13806       Info = add_b23 (plci, bp);
13807       if (Info != GOOD)
13808       {
13809         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13810           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13811         break;
13812       }
13813       plci->internal_command = plci->adjust_b_command;
13814       nl_req_ncci (plci, ASSIGN, 0);
13815       send_req (plci);
13816       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13817       break;
13818     }
13819     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13820     Rc = ASSIGN_OK;
13821   case ADJUST_B_ASSIGN_L23_2:
13822     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13823     {
13824       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13825         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13826       Info = _WRONG_STATE;
13827       break;
13828     }
13829     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13830     {
13831       if (Rc != ASSIGN_OK)
13832       {
13833         plci->internal_command = plci->adjust_b_command;
13834         break;
13835       }
13836     }
13837     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13838     {
13839       plci->adjust_b_restore = true;
13840       break;
13841     }
13842     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13843   case ADJUST_B_CONNECT_1:
13844     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13845     {
13846       plci->internal_command = plci->adjust_b_command;
13847       if (plci_nl_busy (plci))
13848         break;
13849       nl_req_ncci (plci, N_CONNECT, 0);
13850       send_req (plci);
13851       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13852       break;
13853     }
13854     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13855     Rc = OK;
13856   case ADJUST_B_CONNECT_2:
13857   case ADJUST_B_CONNECT_3:
13858   case ADJUST_B_CONNECT_4:
13859     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13860     {
13861       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13862         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13863       Info = _WRONG_STATE;
13864       break;
13865     }
13866     if (Rc == OK)
13867     {
13868       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13869       {
13870         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13871         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13872       }
13873       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13874         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13875       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13876         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13877     }
13878     else if (Rc == 0)
13879     {
13880       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13882       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13883         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13884     }
13885     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13886     {
13887       plci->internal_command = plci->adjust_b_command;
13888       break;
13889     }
13890     Rc = OK;
13891   case ADJUST_B_RESTORE_DTMF_1:
13892   case ADJUST_B_RESTORE_DTMF_2:
13893     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13894     {
13895
13896       Info = dtmf_restore_config (Id, plci, Rc);
13897       if ((Info != GOOD) || plci->internal_command)
13898         break;
13899
13900     }
13901     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13902     Rc = OK;
13903   case ADJUST_B_RESTORE_MIXER_1:
13904   case ADJUST_B_RESTORE_MIXER_2:
13905   case ADJUST_B_RESTORE_MIXER_3:
13906   case ADJUST_B_RESTORE_MIXER_4:
13907   case ADJUST_B_RESTORE_MIXER_5:
13908   case ADJUST_B_RESTORE_MIXER_6:
13909   case ADJUST_B_RESTORE_MIXER_7:
13910     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13911     {
13912
13913       Info = mixer_restore_config (Id, plci, Rc);
13914       if ((Info != GOOD) || plci->internal_command)
13915         break;
13916
13917     }
13918     plci->adjust_b_state = ADJUST_B_END;
13919   case ADJUST_B_END:
13920     break;
13921   }
13922   return (Info);
13923 }
13924
13925
13926 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13927 {
13928
13929   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13930     UnMapId (Id), (char   *)(FILE_), __LINE__,
13931     plci->B1_resource, b1_facilities));
13932
13933   plci->adjust_b_parms_msg = bp_msg;
13934   plci->adjust_b_facilities = b1_facilities;
13935   plci->adjust_b_command = internal_command;
13936   plci->adjust_b_ncci = (word)(Id >> 16);
13937   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13938     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13939   else
13940     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13941   plci->adjust_b_state = ADJUST_B_START;
13942   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13943     UnMapId (Id), (char   *)(FILE_), __LINE__,
13944     plci->B1_resource, b1_facilities));
13945 }
13946
13947
13948 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13949 {
13950   word internal_command;
13951
13952   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13953     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13954
13955   internal_command = plci->internal_command;
13956   plci->internal_command = 0;
13957   switch (internal_command)
13958   {
13959   default:
13960     plci->command = 0;
13961     if (plci->req_in != 0)
13962     {
13963       plci->internal_command = ADJUST_B_RESTORE_1;
13964       break;
13965     }
13966     Rc = OK;
13967   case ADJUST_B_RESTORE_1:
13968     if ((Rc != OK) && (Rc != OK_FC))
13969     {
13970       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13971         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13972     }
13973     plci->adjust_b_parms_msg = NULL;
13974     plci->adjust_b_facilities = plci->B1_facilities;
13975     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13976     plci->adjust_b_ncci = (word)(Id >> 16);
13977     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13978     plci->adjust_b_state = ADJUST_B_START;
13979     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13980       UnMapId (Id), (char   *)(FILE_), __LINE__));
13981   case ADJUST_B_RESTORE_2:
13982     if (adjust_b_process (Id, plci, Rc) != GOOD)
13983     {
13984       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13985         UnMapId (Id), (char   *)(FILE_), __LINE__));
13986     }
13987     if (plci->internal_command)
13988       break;
13989     break;
13990   }
13991 }
13992
13993
13994 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
13995 {
13996   word Info;
13997   word internal_command;
13998
13999   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14000     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14001
14002   Info = GOOD;
14003   internal_command = plci->internal_command;
14004   plci->internal_command = 0;
14005   switch (internal_command)
14006   {
14007   default:
14008     plci->command = 0;
14009     plci->adjust_b_parms_msg = NULL;
14010     plci->adjust_b_facilities = plci->B1_facilities;
14011     plci->adjust_b_command = RESET_B3_COMMAND_1;
14012     plci->adjust_b_ncci = (word)(Id >> 16);
14013     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14014     plci->adjust_b_state = ADJUST_B_START;
14015     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14016       UnMapId (Id), (char   *)(FILE_), __LINE__));
14017   case RESET_B3_COMMAND_1:
14018     Info = adjust_b_process (Id, plci, Rc);
14019     if (Info != GOOD)
14020     {
14021       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14022         UnMapId (Id), (char   *)(FILE_), __LINE__));
14023       break;
14024     }
14025     if (plci->internal_command)
14026       return;
14027     break;
14028   }
14029 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14030   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14031 }
14032
14033
14034 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14035 {
14036   word Info;
14037   word internal_command;
14038   byte esc_chi[3];
14039
14040   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14041     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14042
14043   Info = GOOD;
14044   internal_command = plci->internal_command;
14045   plci->internal_command = 0;
14046   switch (internal_command)
14047   {
14048   default:
14049     plci->command = 0;
14050     plci->adjust_b_parms_msg = &plci->saved_msg;
14051     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14052       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14053     else
14054       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14055     plci->adjust_b_command = SELECT_B_COMMAND_1;
14056     plci->adjust_b_ncci = (word)(Id >> 16);
14057     if (plci->saved_msg.parms[0].length == 0)
14058     {
14059       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14060         ADJUST_B_MODE_NO_RESOURCE;
14061     }
14062     else
14063     {
14064       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14065         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14066     }
14067     plci->adjust_b_state = ADJUST_B_START;
14068     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14069       UnMapId (Id), (char   *)(FILE_), __LINE__));
14070   case SELECT_B_COMMAND_1:
14071     Info = adjust_b_process (Id, plci, Rc);
14072     if (Info != GOOD)
14073     {
14074       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14075         UnMapId (Id), (char   *)(FILE_), __LINE__));
14076       break;
14077     }
14078     if (plci->internal_command)
14079       return;
14080     if (plci->tel == ADV_VOICE)
14081     {
14082       esc_chi[0] = 0x02;
14083       esc_chi[1] = 0x18;
14084       esc_chi[2] = plci->b_channel;
14085       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14086     }
14087     break;
14088   }
14089   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14090 }
14091
14092
14093 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14094 {
14095   word Info;
14096   word internal_command;
14097
14098   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14099     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14100
14101   Info = GOOD;
14102   internal_command = plci->internal_command;
14103   plci->internal_command = 0;
14104   switch (internal_command)
14105   {
14106   default:
14107     plci->command = 0;
14108   case FAX_CONNECT_ACK_COMMAND_1:
14109     if (plci_nl_busy (plci))
14110     {
14111       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14112       return;
14113     }
14114     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14115     plci->NData[0].P = plci->fax_connect_info_buffer;
14116     plci->NData[0].PLength = plci->fax_connect_info_length;
14117     plci->NL.X = plci->NData;
14118     plci->NL.ReqCh = 0;
14119     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14120     plci->adapter->request (&plci->NL);
14121     return;
14122   case FAX_CONNECT_ACK_COMMAND_2:
14123     if ((Rc != OK) && (Rc != OK_FC))
14124     {
14125       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14126         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14127       break;
14128     }
14129   }
14130   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14131    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14132   {
14133     if (plci->B3_prot == 4)
14134       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14135     else
14136       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14137     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14138   }
14139 }
14140
14141
14142 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14143 {
14144   word Info;
14145   word internal_command;
14146
14147   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14148     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14149
14150   Info = GOOD;
14151   internal_command = plci->internal_command;
14152   plci->internal_command = 0;
14153   switch (internal_command)
14154   {
14155   default:
14156     plci->command = 0;
14157   case FAX_EDATA_ACK_COMMAND_1:
14158     if (plci_nl_busy (plci))
14159     {
14160       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14161       return;
14162     }
14163     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14164     plci->NData[0].P = plci->fax_connect_info_buffer;
14165     plci->NData[0].PLength = plci->fax_edata_ack_length;
14166     plci->NL.X = plci->NData;
14167     plci->NL.ReqCh = 0;
14168     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14169     plci->adapter->request (&plci->NL);
14170     return;
14171   case FAX_EDATA_ACK_COMMAND_2:
14172     if ((Rc != OK) && (Rc != OK_FC))
14173     {
14174       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14175         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14176       break;
14177     }
14178   }
14179 }
14180
14181
14182 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14183 {
14184   word Info;
14185   word internal_command;
14186
14187   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14188     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14189
14190   Info = GOOD;
14191   internal_command = plci->internal_command;
14192   plci->internal_command = 0;
14193   switch (internal_command)
14194   {
14195   default:
14196     plci->command = 0;
14197   case FAX_CONNECT_INFO_COMMAND_1:
14198     if (plci_nl_busy (plci))
14199     {
14200       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14201       return;
14202     }
14203     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14204     plci->NData[0].P = plci->fax_connect_info_buffer;
14205     plci->NData[0].PLength = plci->fax_connect_info_length;
14206     plci->NL.X = plci->NData;
14207     plci->NL.ReqCh = 0;
14208     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14209     plci->adapter->request (&plci->NL);
14210     return;
14211   case FAX_CONNECT_INFO_COMMAND_2:
14212     if ((Rc != OK) && (Rc != OK_FC))
14213     {
14214       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14215         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14216       Info = _WRONG_STATE;
14217       break;
14218     }
14219     if (plci_nl_busy (plci))
14220     {
14221       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14222       return;
14223     }
14224     plci->command = _CONNECT_B3_R;
14225     nl_req_ncci (plci, N_CONNECT, 0);
14226     send_req (plci);
14227     return;
14228   }
14229   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14230 }
14231
14232
14233 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14234 {
14235   word Info;
14236   word internal_command;
14237
14238   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14239     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14240
14241   Info = GOOD;
14242   internal_command = plci->internal_command;
14243   plci->internal_command = 0;
14244   switch (internal_command)
14245   {
14246   default:
14247     plci->command = 0;
14248     plci->adjust_b_parms_msg = NULL;
14249     plci->adjust_b_facilities = plci->B1_facilities;
14250     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14251     plci->adjust_b_ncci = (word)(Id >> 16);
14252     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14253     plci->adjust_b_state = ADJUST_B_START;
14254     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14255       UnMapId (Id), (char   *)(FILE_), __LINE__));
14256   case FAX_ADJUST_B23_COMMAND_1:
14257     Info = adjust_b_process (Id, plci, Rc);
14258     if (Info != GOOD)
14259     {
14260       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14261         UnMapId (Id), (char   *)(FILE_), __LINE__));
14262       break;
14263     }
14264     if (plci->internal_command)
14265       return;
14266   case FAX_ADJUST_B23_COMMAND_2:
14267     if (plci_nl_busy (plci))
14268     {
14269       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14270       return;
14271     }
14272     plci->command = _CONNECT_B3_R;
14273     nl_req_ncci (plci, N_CONNECT, 0);
14274     send_req (plci);
14275     return;
14276   }
14277   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14278 }
14279
14280
14281 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14282 {
14283   word internal_command;
14284
14285   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14286     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14287
14288   internal_command = plci->internal_command;
14289   plci->internal_command = 0;
14290   switch (internal_command)
14291   {
14292   default:
14293     plci->command = 0;
14294     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14295     return;
14296   case FAX_DISCONNECT_COMMAND_1:
14297   case FAX_DISCONNECT_COMMAND_2:
14298   case FAX_DISCONNECT_COMMAND_3:
14299     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14300     {
14301       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14302         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14303       break;
14304     }
14305     if (Rc == OK)
14306     {
14307       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14308        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14309       {
14310         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14311       }
14312     }
14313     else if (Rc == 0)
14314     {
14315       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14316         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14317     }
14318     return;
14319   }
14320 }
14321
14322
14323
14324 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14325 {
14326   word Info;
14327   word internal_command;
14328
14329   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14330     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14331
14332   Info = GOOD;
14333   internal_command = plci->internal_command;
14334   plci->internal_command = 0;
14335   switch (internal_command)
14336   {
14337   default:
14338     plci->command = 0;
14339   case RTP_CONNECT_B3_REQ_COMMAND_1:
14340     if (plci_nl_busy (plci))
14341     {
14342       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14343       return;
14344     }
14345     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14346     nl_req_ncci (plci, N_CONNECT, 0);
14347     send_req (plci);
14348     return;
14349   case RTP_CONNECT_B3_REQ_COMMAND_2:
14350     if ((Rc != OK) && (Rc != OK_FC))
14351     {
14352       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14353         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14354       Info = _WRONG_STATE;
14355       break;
14356     }
14357     if (plci_nl_busy (plci))
14358     {
14359       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14360       return;
14361     }
14362     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14363     plci->NData[0].PLength = plci->internal_req_buffer[0];
14364     plci->NData[0].P = plci->internal_req_buffer + 1;
14365     plci->NL.X = plci->NData;
14366     plci->NL.ReqCh = 0;
14367     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14368     plci->adapter->request (&plci->NL);
14369     break;
14370   case RTP_CONNECT_B3_REQ_COMMAND_3:
14371     return;
14372   }
14373   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14374 }
14375
14376
14377 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14378 {
14379   word Info;
14380   word internal_command;
14381
14382   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14383     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14384
14385   Info = GOOD;
14386   internal_command = plci->internal_command;
14387   plci->internal_command = 0;
14388   switch (internal_command)
14389   {
14390   default:
14391     plci->command = 0;
14392   case RTP_CONNECT_B3_RES_COMMAND_1:
14393     if (plci_nl_busy (plci))
14394     {
14395       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14396       return;
14397     }
14398     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14399     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14400     send_req (plci);
14401     return;
14402   case RTP_CONNECT_B3_RES_COMMAND_2:
14403     if ((Rc != OK) && (Rc != OK_FC))
14404     {
14405       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14406         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14407       Info = _WRONG_STATE;
14408       break;
14409     }
14410     if (plci_nl_busy (plci))
14411     {
14412       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14413       return;
14414     }
14415     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14416     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14417     plci->NData[0].PLength = plci->internal_req_buffer[0];
14418     plci->NData[0].P = plci->internal_req_buffer + 1;
14419     plci->NL.X = plci->NData;
14420     plci->NL.ReqCh = 0;
14421     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14422     plci->adapter->request (&plci->NL);
14423     return;
14424   case RTP_CONNECT_B3_RES_COMMAND_3:
14425     return;
14426   }
14427 }
14428
14429
14430
14431 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14432 {
14433     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14434   word Info;
14435   word internal_command;
14436
14437   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14438     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14439
14440   Info = GOOD;
14441   internal_command = plci->internal_command;
14442   plci->internal_command = 0;
14443   switch (internal_command)
14444   {
14445   default:
14446     if (!plci->NL.Id)
14447       break;
14448     plci->command = 0;
14449     plci->adjust_b_parms_msg = NULL;
14450     plci->adjust_b_facilities = plci->B1_facilities;
14451     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14452     plci->adjust_b_ncci = (word)(Id >> 16);
14453     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14454     plci->adjust_b_state = ADJUST_B_START;
14455     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14456       UnMapId (Id), (char   *)(FILE_), __LINE__));
14457   case HOLD_SAVE_COMMAND_1:
14458     Info = adjust_b_process (Id, plci, Rc);
14459     if (Info != GOOD)
14460     {
14461       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14462         UnMapId (Id), (char   *)(FILE_), __LINE__));
14463       break;
14464     }
14465     if (plci->internal_command)
14466       return;
14467   }
14468   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14469 }
14470
14471
14472 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14473 {
14474     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14475   word Info;
14476   word internal_command;
14477
14478   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14479     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14480
14481   Info = GOOD;
14482   internal_command = plci->internal_command;
14483   plci->internal_command = 0;
14484   switch (internal_command)
14485   {
14486   default:
14487     plci->command = 0;
14488     plci->adjust_b_parms_msg = NULL;
14489     plci->adjust_b_facilities = plci->B1_facilities;
14490     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14491     plci->adjust_b_ncci = (word)(Id >> 16);
14492     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14493     plci->adjust_b_state = ADJUST_B_START;
14494     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14495       UnMapId (Id), (char   *)(FILE_), __LINE__));
14496   case RETRIEVE_RESTORE_COMMAND_1:
14497     Info = adjust_b_process (Id, plci, Rc);
14498     if (Info != GOOD)
14499     {
14500       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14501         UnMapId (Id), (char   *)(FILE_), __LINE__));
14502       break;
14503     }
14504     if (plci->internal_command)
14505       return;
14506   }
14507   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14508 }
14509
14510
14511 static void init_b1_config (PLCI   *plci)
14512 {
14513
14514   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14515     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14516     (char   *)(FILE_), __LINE__));
14517
14518   plci->B1_resource = 0;
14519   plci->B1_facilities = 0;
14520
14521   plci->li_bchannel_id = 0;
14522   mixer_clear_config (plci);
14523
14524
14525   ec_clear_config (plci);
14526
14527
14528   dtmf_rec_clear_config (plci);
14529   dtmf_send_clear_config (plci);
14530   dtmf_parameter_clear_config (plci);
14531
14532   adv_voice_clear_config (plci);
14533   adjust_b_clear (plci);
14534 }
14535
14536
14537 static void clear_b1_config (PLCI   *plci)
14538 {
14539
14540   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14541     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14542     (char   *)(FILE_), __LINE__));
14543
14544   adv_voice_clear_config (plci);
14545   adjust_b_clear (plci);
14546
14547   ec_clear_config (plci);
14548
14549
14550   dtmf_rec_clear_config (plci);
14551   dtmf_send_clear_config (plci);
14552   dtmf_parameter_clear_config (plci);
14553
14554
14555   if ((plci->li_bchannel_id != 0)
14556    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14557   {
14558     mixer_clear_config (plci);
14559     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14560     plci->li_bchannel_id = 0;
14561   }
14562
14563   plci->B1_resource = 0;
14564   plci->B1_facilities = 0;
14565 }
14566
14567
14568 /* -----------------------------------------------------------------
14569                 XON protocol local helpers
14570    ----------------------------------------------------------------- */
14571 static void channel_flow_control_remove (PLCI   * plci) {
14572   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14573   word i;
14574   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14575     if (a->ch_flow_plci[i] == plci->Id) {
14576       a->ch_flow_plci[i] = 0;
14577       a->ch_flow_control[i] = 0;
14578     }
14579   }
14580 }
14581
14582 static void channel_x_on (PLCI   * plci, byte ch) {
14583   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14584   if (a->ch_flow_control[ch] & N_XON_SENT) {
14585     a->ch_flow_control[ch] &= ~N_XON_SENT;
14586   }
14587 }
14588
14589 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14590   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14591   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14592     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14593     a->ch_flow_plci[ch] = plci->Id;
14594     a->ch_flow_control_pending++;
14595   }
14596 }
14597
14598 static void channel_request_xon (PLCI   * plci, byte ch) {
14599   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14600
14601   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14602     a->ch_flow_control[ch] |= N_XON_REQ;
14603     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14604     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14605   }
14606 }
14607
14608 static void channel_xmit_extended_xon (PLCI   * plci) {
14609   DIVA_CAPI_ADAPTER   * a;
14610   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14611   int i, one_requested = 0;
14612
14613   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14614     return;
14615   }
14616
14617   for (i = 0; i < max_ch; i++) {
14618     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14619         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14620         (plci->Id == a->ch_flow_plci[i])) {
14621       channel_request_xon (plci, (byte)i);
14622       one_requested = 1;
14623     }
14624   }
14625
14626   if (one_requested) {
14627     channel_xmit_xon (plci);
14628   }
14629 }
14630
14631 /*
14632   Try to xmit next X_ON
14633   */
14634 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14635   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14636   int i;
14637
14638   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14639     return (0);
14640   }
14641
14642   if (a->last_flow_control_ch >= max_ch) {
14643     a->last_flow_control_ch = 1;
14644   }
14645   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14646     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14647         (plci->Id == a->ch_flow_plci[i])) {
14648       a->last_flow_control_ch = i+1;
14649       return (i);
14650     }
14651   }
14652
14653   for (i = 1; i < a->last_flow_control_ch; i++) {
14654     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14655         (plci->Id == a->ch_flow_plci[i])) {
14656       a->last_flow_control_ch = i+1;
14657       return (i);
14658     }
14659   }
14660
14661   return (0);
14662 }
14663
14664 static void channel_xmit_xon (PLCI   * plci) {
14665   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14666   byte ch;
14667
14668   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14669     return;
14670   }
14671   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14672     return;
14673   }
14674   a->ch_flow_control[ch] &= ~N_XON_REQ;
14675   a->ch_flow_control[ch] |= N_XON_SENT;
14676
14677   plci->NL.Req = plci->nl_req = (byte)N_XON;
14678   plci->NL.ReqCh         = ch;
14679   plci->NL.X             = plci->NData;
14680   plci->NL.XNum          = 1;
14681   plci->NData[0].P       = &plci->RBuffer[0];
14682   plci->NData[0].PLength = 0;
14683
14684   plci->adapter->request(&plci->NL);
14685 }
14686
14687 static int channel_can_xon (PLCI   * plci, byte ch) {
14688   APPL   * APPLptr;
14689   DIVA_CAPI_ADAPTER   * a;
14690   word NCCIcode;
14691   dword count;
14692   word Num;
14693   word i;
14694
14695   APPLptr = plci->appl;
14696   a = plci->adapter;
14697
14698   if (!APPLptr)
14699     return (0);
14700
14701   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14702
14703                 /* count all buffers within the Application pool    */
14704                 /* belonging to the same NCCI. XON if a first is    */
14705                 /* used.                                            */
14706   count = 0;
14707   Num = 0xffff;
14708   for(i=0; i<APPLptr->MaxBuffer; i++) {
14709     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14710     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14711   }
14712   if ((count > 2) || (Num == 0xffff)) {
14713     return (0);
14714   }
14715   return (1);
14716 }
14717
14718
14719 /*------------------------------------------------------------------*/
14720
14721 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14722 {
14723   return 1;
14724 }
14725
14726
14727
14728 /**********************************************************************************/
14729 /* function groups the listening applications according to the CIP mask and the   */
14730 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14731 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14732 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14733 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14734 /* OS specific part (per adapter).                                                */
14735 /**********************************************************************************/
14736 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14737 {
14738   word i,j,k,busy,group_found;
14739   dword info_mask_group[MAX_CIP_TYPES];
14740   dword cip_mask_group[MAX_CIP_TYPES];
14741   word appl_number_group_type[MAX_APPL];
14742   PLCI   *auxplci;
14743
14744   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14745
14746   if(!a->group_optimization_enabled)
14747   {
14748     dbug(1,dprintf("No group optimization"));
14749     return;
14750   }
14751
14752   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14753
14754   for(i=0;i<MAX_CIP_TYPES;i++)
14755   {
14756     info_mask_group[i] = 0;
14757     cip_mask_group [i] = 0;
14758   }
14759   for(i=0;i<MAX_APPL;i++)
14760   {
14761     appl_number_group_type[i] = 0;
14762   }
14763   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14764   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14765     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14766     {
14767       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14768       return; /* allow good application unfiltered access */
14769     }
14770   }
14771   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14772   {
14773     if(application[i].Id && a->CIP_Mask[i] )
14774     {
14775       for(k=0,busy=false; k<a->max_plci; k++)
14776       {
14777         if(a->plci[k].Id) 
14778         {
14779           auxplci = &a->plci[k];
14780           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14781           {
14782             busy = true;
14783             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14784           }
14785           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14786           {
14787             busy = true;
14788             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14789           }
14790         }
14791       }
14792
14793       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14794       {
14795         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14796         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14797           appl_number_group_type[i] = MAX_CIP_TYPES;
14798           group_found=true;
14799           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14800         }
14801         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14802         {                                      /* is group already present ?                  */
14803           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14804           group_found=true;
14805           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]));
14806         }
14807         else if(!info_mask_group[j])
14808         {                                      /* establish a new group                       */
14809           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14810           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14811           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14812           group_found=true;
14813           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]));
14814         }
14815       }
14816     }
14817   }
14818         
14819   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14820   {
14821     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14822     {
14823       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14824       {
14825         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14826       }
14827       else
14828       {
14829         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14830         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14831         {
14832           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14833           {
14834             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14835             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14836             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14837           }
14838         }
14839       }
14840     }
14841     else                                                 /* application should not get a call */
14842     {
14843       clear_group_ind_mask_bit (plci, i);
14844     }
14845   }
14846
14847 }
14848
14849
14850
14851 /* OS notifies the driver about a application Capi_Register */
14852 word CapiRegister(word id)
14853 {
14854   word i,j,appls_found;
14855
14856   PLCI   *plci;
14857   DIVA_CAPI_ADAPTER   *a;
14858
14859   for(i=0,appls_found=0; i<max_appl; i++)
14860   {
14861     if( application[i].Id && (application[i].Id!=id) )
14862     {
14863       appls_found++;                       /* an application has been found */
14864     }
14865   }
14866
14867   if(appls_found) return true;
14868   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14869   {
14870     a = &adapter[i];
14871     if(a->request)
14872     {
14873       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14874       {
14875         if(!appls_found)           /* first application does a capi register   */
14876         {
14877           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14878           {
14879             plci = &a->plci[j-1];
14880             plci->command = 0;
14881             add_p(plci,OAD,"\x01\xfd");
14882             add_p(plci,CAI,"\x01\x80");
14883             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14884             add_p(plci,SHIFT|6,NULL);
14885             add_p(plci,SIN,"\x02\x00\x00");
14886             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14887             sig_req(plci,ASSIGN,DSIG_ID);
14888             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14889             sig_req(plci,SIG_CTRL,0);
14890             send_req(plci);
14891           }
14892         }
14893       }
14894     }
14895   }
14896   return false;
14897 }
14898
14899 /*------------------------------------------------------------------*/
14900
14901 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14902
14903 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14904 {
14905  word i;
14906  /* Format of vswitch_t:
14907  0 byte length
14908  1 byte VSWITCHIE
14909  2 byte VSWITCH_REQ/VSWITCH_IND
14910  3 byte reserved
14911  4 word VSwitchcommand
14912  6 word returnerror
14913  8... Params
14914  */
14915  if(!plci ||
14916   !plci->appl ||
14917   !plci->State ||
14918   plci->Sig.Ind==NCR_FACILITY
14919   )
14920   return;
14921  
14922  for(i=0;i<MAX_MULTI_IE;i++)
14923  {
14924         if(!parms[i][0]) continue;
14925   if(parms[i][0]<7)
14926   {
14927    parms[i][0]=0; /* kill it */
14928    continue;
14929   }
14930   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14931   switch(parms[i][4])
14932   {
14933   case VSJOIN:
14934    if(!plci->relatedPTYPLCI ||
14935     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14936    { /* Error */
14937     break;
14938    }
14939    /* remember all necessary informations */
14940    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14941    {
14942     break;
14943    }
14944    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14945    {   /* first indication after ECT-Request on Consultation Call */
14946     plci->vswitchstate=parms[i][9];
14947     parms[i][9]=2; /* State */
14948     /* now ask first Call to join */
14949    }
14950    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14951    { /* Answer of VSWITCH_REQ from first Call */
14952     plci->vswitchstate=parms[i][9];
14953     /* tell consultation call to join
14954     and the protocol capabilities of the first call */
14955    }
14956    else
14957    { /* Error */
14958     break;
14959    }    
14960    plci->vsprot=parms[i][10]; /* protocol */
14961    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14962    /* send join request to related PLCI */
14963    parms[i][1]=VSWITCHIE;
14964    parms[i][2]=VSWITCH_REQ;
14965    
14966    plci->relatedPTYPLCI->command = 0;
14967    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14968    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14969    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14970    send_req(plci->relatedPTYPLCI);
14971    break;
14972   case VSTRANSPORT:
14973   default:
14974    if(plci->relatedPTYPLCI &&
14975     plci->vswitchstate==3 &&
14976     plci->relatedPTYPLCI->vswitchstate==3)
14977    {
14978     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14979     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14980     send_req(plci->relatedPTYPLCI);
14981    }
14982    break;
14983   }  
14984   parms[i][0]=0; /* kill it */
14985  }
14986 }
14987
14988
14989 /*------------------------------------------------------------------*/
14990
14991 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
14992   ENTITY e;
14993   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14994
14995   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14996     return (-1);
14997   }
14998
14999   pReq->xdi_dma_descriptor_operation.Req = 0;
15000   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15001
15002   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15003   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15004   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15005   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15006
15007   e.user[0] = plci->adapter->Id - 1;
15008   plci->adapter->request((ENTITY*)pReq);
15009
15010   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15011       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15012       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15013     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15014     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15015          plci->adapter->Id,
15016          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15017          *dma_magic));
15018     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15019   } else {
15020     dbug(1,dprintf("dma_alloc failed"));
15021     return (-1);
15022   }
15023 }
15024
15025 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15026   ENTITY e;
15027   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15028
15029   if (nr < 0) {
15030     return;
15031   }
15032
15033   pReq->xdi_dma_descriptor_operation.Req = 0;
15034   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15035
15036   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15037   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15038   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15039   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15040
15041   e.user[0] = plci->adapter->Id - 1;
15042   plci->adapter->request((ENTITY*)pReq);
15043
15044   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15045     dbug(1,dprintf("dma_free(%d)", nr));
15046   } else {
15047     dbug(1,dprintf("dma_free failed (%d)", nr));
15048   }
15049 }
15050
15051 /*------------------------------------------------------------------*/