8fcc595633fe7078efe11cf5c03f781347e3c8fe
[linux-flexiantxendom0-3.2.10.git] / drivers / isdn / hardware / eicon / message.c
1
2 /*
3  *
4   Copyright (c) Eicon Networks, 2002.
5  *
6   This source file is supplied for the use with
7   Eicon Networks range of DIVA Server Adapters.
8  *
9   Eicon File Revision :    2.1
10  *
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2, or (at your option)
14   any later version.
15  *
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19   See the GNU General Public License for more details.
20  *
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27
28
29
30
31 #include "platform.h"
32 #include "di_defs.h"
33 #include "pc.h"
34 #include "capi20.h"
35 #include "divacapi.h"
36 #include "mdm_msg.h"
37 #include "divasync.h"
38
39
40
41 #define FILE_ "MESSAGE.C"
42 #define dprintf
43
44
45
46
47
48
49
50
51
52 /*------------------------------------------------------------------*/
53 /* This is options supported for all adapters that are server by    */
54 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
55 /* and it is not necessary to save it separate for every adapter    */
56 /* Macrose defined here have only local meaning                     */
57 /*------------------------------------------------------------------*/
58 dword diva_xdi_extended_features = 0;
59
60 #define DIVA_CAPI_USE_CMA                 0x00000001
61 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
62 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
63 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
64
65 /*
66   CAPI can request to process all return codes self only if:
67   protocol code supports this && xdi supports this
68  */
69 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
70
71 /*------------------------------------------------------------------*/
72 /* local function prototypes                                        */
73 /*------------------------------------------------------------------*/
74
75 void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
76 void set_group_ind_mask (PLCI   *plci);
77 void set_group_ind_mask_bit (PLCI   *plci, word b);
78 void clear_group_ind_mask_bit (PLCI   *plci, word b);
79 byte test_group_ind_mask_bit (PLCI   *plci, word b);
80 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
81 word CapiRelease(word);
82 word CapiRegister(word);
83 word api_put(APPL   *, CAPI_MSG   *);
84 static word api_parse(byte   *, word, byte *, API_PARSE *);
85 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
86 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
87
88 word api_remove_start(void);
89 void api_remove_complete(void);
90
91 void plci_remove(PLCI   *);
92 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
93 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
94
95 void   callback(ENTITY   *);
96
97 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
98 static void data_rc(PLCI   *, byte);
99 static void data_ack(PLCI   *, byte);
100 static void sig_ind(PLCI   *);
101 static void SendInfo(PLCI   *, dword, byte   * *, byte);
102 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
103 void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
104
105 void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
106
107 static void nl_ind(PLCI   *);
108
109 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
132 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
133
134 static word get_plci(DIVA_CAPI_ADAPTER   *);
135 static void add_p(PLCI   *, byte, byte   *);
136 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
137 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
138 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
139 static void add_d(PLCI   *, word, byte   *);
140 static void add_ai(PLCI   *, API_PARSE *);
141 static word add_b1(PLCI   *, API_PARSE *, word, word);
142 static word add_b23(PLCI   *, API_PARSE *);
143 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
144 static void sig_req(PLCI   *, byte, byte);
145 static void nl_req_ncci(PLCI   *, byte, byte);
146 static void send_req(PLCI   *);
147 static void send_data(PLCI   *);
148 static word plci_remove_check(PLCI   *);
149 static void listen_check(DIVA_CAPI_ADAPTER   *);
150 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
151 static byte getChannel(API_PARSE *);
152 static void IndParse(PLCI   *, word *, byte   **, byte);
153 static byte ie_compare(byte   *, byte *);
154 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
155 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
156
157 /*
158   XON protocol helpers
159   */
160 static void channel_flow_control_remove (PLCI   * plci);
161 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
162 static void channel_x_on (PLCI   * plci, byte ch);
163 static void channel_request_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_xon (PLCI   * plci);
165 static int channel_can_xon (PLCI   * plci, byte ch);
166 static void channel_xmit_extended_xon (PLCI   * plci);
167
168 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
169 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
170 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
171 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
172 static void VoiceChannelOff(PLCI   *plci);
173 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
174 static void adv_voice_clear_config (PLCI   *plci);
175
176 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
177 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
178 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
179 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
180 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
181 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
182 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
183 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
187 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
188 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
189 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
190 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
191 static void init_b1_config (PLCI   *plci);
192 static void clear_b1_config (PLCI   *plci);
193
194 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
195 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
196 static void dtmf_confirmation (dword Id, PLCI   *plci);
197 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
198 static void dtmf_parameter_write (PLCI   *plci);
199
200
201 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
202 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
203 static void mixer_clear_config (PLCI   *plci);
204 static void mixer_notify_update (PLCI   *plci, byte others);
205 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
206 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
207 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
208 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
209 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
210 static void mixer_remove (PLCI   *plci);
211
212
213 static void ec_command (dword Id, PLCI   *plci, byte Rc);
214 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
215 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
216
217
218 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
219 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
220
221
222 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
223 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
224
225 /*------------------------------------------------------------------*/
226 /* external function prototypes                                     */
227 /*------------------------------------------------------------------*/
228
229 extern byte MapController (byte);
230 extern byte UnMapController (byte);
231 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
232 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
233
234 void   sendf(APPL   *, word, dword, word, byte *, ...);
235 void   * TransmitBufferSet(APPL   * appl, dword ref);
236 void   * TransmitBufferGet(APPL   * appl, void   * p);
237 void TransmitBufferFree(APPL   * appl, void   * p);
238 void   * ReceiveBufferGet(APPL   * appl, int Num);
239
240 int fax_head_line_time (char *buffer);
241
242
243 /*------------------------------------------------------------------*/
244 /* Global data definitions                                          */
245 /*------------------------------------------------------------------*/
246 extern byte max_adapter;
247 extern byte max_appl;
248 extern DIVA_CAPI_ADAPTER   * adapter;
249 extern APPL   * application;
250
251
252
253
254
255
256
257 byte remove_started = FALSE;
258 PLCI dummy_plci;
259
260
261 struct _ftable {
262   word command;
263   byte * format;
264   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
265 } ftable[] = {
266   {_DATA_B3_R,                          "dwww",         data_b3_req},
267   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
268   {_INFO_R,                             "ss",           info_req},
269   {_INFO_I|RESPONSE,                    "",             info_res},
270   {_CONNECT_R,                          "wsssssssss",   connect_req},
271   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
272   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
273   {_DISCONNECT_R,                       "s",            disconnect_req},
274   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
275   {_LISTEN_R,                           "dddss",        listen_req},
276   {_ALERT_R,                            "s",            alert_req},
277   {_FACILITY_R,                         "ws",           facility_req},
278   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
279   {_CONNECT_B3_R,                       "s",            connect_b3_req},
280   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
281   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
282   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
283   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
284   {_RESET_B3_R,                         "s",            reset_b3_req},
285   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
286   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
287   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
288   {_SELECT_B_REQ,                       "s",            select_b_req},
289   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
290   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
291   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
292 };
293
294 byte * cip_bc[29][2] = {
295   { "",                     ""                     }, /* 0 */
296   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
297   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
298   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
299   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
300   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
301   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
302   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
303   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
304   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
305   { "",                     ""                     }, /* 10 */
306   { "",                     ""                     }, /* 11 */
307   { "",                     ""                     }, /* 12 */
308   { "",                     ""                     }, /* 13 */
309   { "",                     ""                     }, /* 14 */
310   { "",                     ""                     }, /* 15 */
311
312   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
313   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
320   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
321   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
322   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
323   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
324   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
325 };
326
327 byte * cip_hlc[29] = {
328   "",                           /* 0 */
329   "",                           /* 1 */
330   "",                           /* 2 */
331   "",                           /* 3 */
332   "",                           /* 4 */
333   "",                           /* 5 */
334   "",                           /* 6 */
335   "",                           /* 7 */
336   "",                           /* 8 */
337   "",                           /* 9 */
338   "",                           /* 10 */
339   "",                           /* 11 */
340   "",                           /* 12 */
341   "",                           /* 13 */
342   "",                           /* 14 */
343   "",                           /* 15 */
344
345   "\x02\x91\x81",               /* 16 */
346   "\x02\x91\x84",               /* 17 */
347   "\x02\x91\xa1",               /* 18 */
348   "\x02\x91\xa4",               /* 19 */
349   "\x02\x91\xa8",               /* 20 */
350   "\x02\x91\xb1",               /* 21 */
351   "\x02\x91\xb2",               /* 22 */
352   "\x02\x91\xb5",               /* 23 */
353   "\x02\x91\xb8",               /* 24 */
354   "\x02\x91\xc1",               /* 25 */
355   "\x02\x91\x81",               /* 26 */
356   "\x03\x91\xe0\x01",           /* 27 */
357   "\x03\x91\xe0\x02"            /* 28 */
358 };
359
360 /*------------------------------------------------------------------*/
361
362 #define V120_HEADER_LENGTH 1
363 #define V120_HEADER_EXTEND_BIT  0x80
364 #define V120_HEADER_BREAK_BIT   0x40
365 #define V120_HEADER_C1_BIT      0x04
366 #define V120_HEADER_C2_BIT      0x08
367 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
368
369 static byte v120_default_header[] =
370 {
371
372   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
373
374 };
375
376 static byte v120_break_header[] =
377 {
378
379   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
380
381 };
382
383
384 /*------------------------------------------------------------------*/
385 /* API_PUT function                                                 */
386 /*------------------------------------------------------------------*/
387
388 word api_put(APPL   * appl, CAPI_MSG   * msg)
389 {
390   word i, j, k, l, n;
391   word ret;
392   byte c;
393   byte controller;
394   DIVA_CAPI_ADAPTER   * a;
395   PLCI   * plci;
396   NCCI   * ncci_ptr;
397   word ncci;
398   CAPI_MSG   *m;
399     API_PARSE msg_parms[MAX_MSG_PARMS+1];
400
401   if (msg->header.length < sizeof (msg->header) ||
402       msg->header.length > MAX_MSG_SIZE) {
403     dbug(1,dprintf("bad len"));
404     return _BAD_MSG;
405   }
406
407   controller = (byte)((msg->header.controller &0x7f)-1);
408
409   /* controller starts with 0 up to (max_adapter - 1) */
410   if ( controller >= max_adapter )
411   {
412     dbug(1,dprintf("invalid ctrl"));
413     return _BAD_MSG;
414   }
415   
416   a = &adapter[controller];
417   plci = 0;
418   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
419   {
420     dbug(1,dprintf("plci=%x",msg->header.plci));
421     plci = &a->plci[msg->header.plci-1];
422     ncci = READ_WORD(&msg->header.ncci);
423     if (plci->Id
424      && (plci->appl
425       || (plci->State == INC_CON_PENDING)
426       || (plci->State == INC_CON_ALERT)
427       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
428      && ((ncci == 0)
429       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
430       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
431     {
432       i = plci->msg_in_read_pos;
433       j = plci->msg_in_write_pos;
434       if (j >= i)
435       {
436         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
437           i += MSG_IN_QUEUE_SIZE - j;
438         else
439           j = 0;
440       }
441       else
442       {
443
444         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
445
446         if (i > MSG_IN_QUEUE_SIZE - n)
447           i = MSG_IN_QUEUE_SIZE - n + 1;
448         i -= j;
449       }
450
451       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
452
453       {
454         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
455           msg->header.length, plci->msg_in_write_pos,
456           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
457
458         return _QUEUE_FULL;
459       }
460       c = FALSE;
461       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
462        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
463       {
464         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
465           c = TRUE;
466       }
467       if (msg->header.command == _DATA_B3_R)
468       {
469         if (msg->header.length < 20)
470         {
471           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
472           return _BAD_MSG;
473         }
474         ncci_ptr = &(a->ncci[ncci]);
475         n = ncci_ptr->data_pending;
476         l = ncci_ptr->data_ack_pending;
477         k = plci->msg_in_read_pos;
478         while (k != plci->msg_in_write_pos)
479         {
480           if (k == plci->msg_in_wrap_pos)
481             k = 0;
482           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
483            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
484           {
485             n++;
486             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
487               l++;
488           }
489
490           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
491             MSG_IN_OVERHEAD + 3) & 0xfffc;
492
493         }
494         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
495         {
496           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
497                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
498
499           return _QUEUE_FULL;
500         }
501         if (plci->req_in || plci->internal_command)
502         {
503           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
504            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
505           {
506             dbug(0,dprintf("Q-FULL3(requeue)"));
507
508             return _QUEUE_FULL;
509           }
510           c = TRUE;
511         }
512       }
513       else
514       {
515         if (plci->req_in || plci->internal_command)
516           c = TRUE;
517         else
518         {
519           plci->command = msg->header.command;
520           plci->number = msg->header.number;
521         }
522       }
523       if (c)
524       {
525         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
526           msg->header.command, plci->req_in, plci->internal_command,
527           msg->header.length, plci->msg_in_write_pos,
528           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
529         if (j == 0)
530           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
531         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
532         for (i = 0; i < msg->header.length; i++)
533           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
534         if (m->header.command == _DATA_B3_R)
535         {
536
537           m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
538
539         }
540
541         j = (j + 3) & 0xfffc;
542
543         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
544         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
545         return 0;
546       }
547     }
548     else
549     {
550       plci = 0;
551     }
552   }
553   dbug(1,dprintf("com=%x",msg->header.command));
554
555   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
556   for(i=0, ret = _BAD_MSG;
557       i<(sizeof(ftable)/sizeof(struct _ftable));
558       i++) {
559
560     if(ftable[i].command==msg->header.command) {
561       /* break loop if the message is correct, otherwise continue scan  */
562       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
563       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
564         ret = 0;
565         break;
566       }
567       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
568     }
569   }
570   if(ret) {
571     dbug(1,dprintf("BAD_MSG"));
572     if(plci) plci->command = 0;
573     return ret;
574   }
575
576
577   c = ftable[i].function(READ_DWORD(&msg->header.controller),
578                          msg->header.number,
579                          a,
580                          plci,
581                          appl,
582                          msg_parms);
583
584   channel_xmit_extended_xon (plci);
585
586   if(c==1) send_req(plci);
587   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
588   if(plci && !plci->req_in) plci->command = 0;
589   return 0;
590 }
591
592
593 /*------------------------------------------------------------------*/
594 /* api_parse function, check the format of api messages             */
595 /*------------------------------------------------------------------*/
596
597 word api_parse(byte   * msg, word length, byte * format, API_PARSE * parms)
598 {
599   word i;
600   word p;
601
602   for(i=0,p=0; format[i]; i++) {
603     if(parms)
604     {
605       parms[i].info = &msg[p];
606     }
607     switch(format[i]) {
608     case 'b':
609       p +=1;
610       break;
611     case 'w':
612       p +=2;
613       break;
614     case 'd':
615       p +=4;
616       break;
617     case 's':
618       if(msg[p]==0xff) {
619         parms[i].info +=2;
620         parms[i].length = msg[p+1] + (msg[p+2]<<8);
621         p +=(parms[i].length +3);
622       }
623       else {
624         parms[i].length = msg[p];
625         p +=(parms[i].length +1);
626       }
627       break;
628     }
629
630     if(p>length) return TRUE;
631   }
632   if(parms) parms[i].info = 0;
633   return FALSE;
634 }
635
636 void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
637 {
638   word i, j, n = 0;
639   byte   *p;
640
641   p = out->info;
642   for (i = 0; format[i] != '\0'; i++)
643   {
644     out->parms[i].info = p;
645     out->parms[i].length = in[i].length;
646     switch (format[i])
647     {
648     case 'b':
649       n = 1;
650       break;
651     case 'w':
652       n = 2;
653       break;
654     case 'd':
655       n = 4;
656       break;
657     case 's':
658       n = in[i].length + 1;
659       break;
660     }
661     for (j = 0; j < n; j++)
662       *(p++) = in[i].info[j];
663   }
664   out->parms[i].info = 0;
665   out->parms[i].length = 0;
666 }
667
668 void api_load_msg(API_SAVE   *in, API_PARSE   *out)
669 {
670   word i;
671
672   i = 0;
673   do
674   {
675     out[i].info = in->parms[i].info;
676     out[i].length = in->parms[i].length;
677   } while (in->parms[i++].info);
678 }
679
680
681 /*------------------------------------------------------------------*/
682 /* CAPI remove function                                             */
683 /*------------------------------------------------------------------*/
684
685 word api_remove_start(void)
686 {
687   word i;
688   word j;
689
690   if(!remove_started) {
691     remove_started = TRUE;
692     for(i=0;i<max_adapter;i++) {
693       if(adapter[i].request) {
694         for(j=0;j<adapter[i].max_plci;j++) {
695           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
696         }
697       }
698     }
699     return 1;
700   }
701   else {
702     for(i=0;i<max_adapter;i++) {
703       if(adapter[i].request) {
704         for(j=0;j<adapter[i].max_plci;j++) {
705           if(adapter[i].plci[j].Sig.Id) return 1;
706         }
707       }
708     }
709   }
710   api_remove_complete();
711   return 0;
712 }
713
714
715 /*------------------------------------------------------------------*/
716 /* internal command queue                                           */
717 /*------------------------------------------------------------------*/
718
719 void init_internal_command_queue (PLCI   *plci)
720 {
721   word i;
722
723   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
724     (char   *)(FILE_), __LINE__));
725
726   plci->internal_command = 0;
727   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
728     plci->internal_command_queue[i] = 0;
729 }
730
731
732 void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
733 {
734   word i;
735
736   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
737     UnMapId (Id), (char   *)(FILE_), __LINE__));
738
739   if (plci->internal_command == 0)
740   {
741     plci->internal_command_queue[0] = command_function;
742     (* command_function)(Id, plci, OK);
743   }
744   else
745   {
746     i = 1;
747     while (plci->internal_command_queue[i] != 0)
748       i++;
749     plci->internal_command_queue[i] = command_function;
750   }
751 }
752
753
754 void next_internal_command (dword Id, PLCI   *plci)
755 {
756   word i;
757
758   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
759     UnMapId (Id), (char   *)(FILE_), __LINE__));
760
761   plci->internal_command = 0;
762   plci->internal_command_queue[0] = 0;
763   while (plci->internal_command_queue[1] != 0)
764   {
765     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
766       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
767     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = 0;
768     (*(plci->internal_command_queue[0]))(Id, plci, OK);
769     if (plci->internal_command != 0)
770       return;
771     plci->internal_command_queue[0] = 0;
772   }
773 }
774
775
776 /*------------------------------------------------------------------*/
777 /* NCCI allocate/remove function                                    */
778 /*------------------------------------------------------------------*/
779
780 static dword ncci_mapping_bug = 0;
781
782 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
783 {
784   DIVA_CAPI_ADAPTER   *a;
785   word ncci, i, j, k;
786
787   a = plci->adapter;
788   if (!ch || a->ch_ncci[ch])
789   {
790     ncci_mapping_bug++;
791     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
792       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
793     ncci = ch;
794   }
795   else
796   {
797     if (force_ncci)
798       ncci = force_ncci;
799     else
800     {
801       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
802         ncci = ch;
803       else
804       {
805         ncci = 1;
806         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
807           ncci++;
808         if (ncci == MAX_NCCI+1)
809         {
810           ncci_mapping_bug++;
811           i = 1;
812           do
813           {
814             j = 1;
815             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
816               j++;
817             k = j;
818             if (j < MAX_NCCI+1)
819             {
820               do
821               {
822                 j++;
823               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
824             }
825           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
826           if (i < MAX_NL_CHANNEL+1)
827           {
828             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
829               ncci_mapping_bug, ch, force_ncci, i, k, j));
830           }
831           else
832           {
833             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
834               ncci_mapping_bug, ch, force_ncci));
835           }
836           ncci = ch;
837         }
838       }
839       a->ncci_plci[ncci] = plci->Id;
840       a->ncci_state[ncci] = IDLE;
841       if (!plci->ncci_ring_list)
842         plci->ncci_ring_list = ncci;
843       else
844         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
845       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
846     }
847     a->ncci_ch[ncci] = ch;
848     a->ch_ncci[ch] = (byte) ncci;
849     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
850       ncci_mapping_bug, ch, force_ncci, ch, ncci));
851   }
852   return (ncci);
853 }
854
855
856 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
857 {
858   DIVA_CAPI_ADAPTER   *a;
859   APPL   *appl;
860   word i, ncci_code;
861   dword Id;
862
863   a = plci->adapter;
864   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
865   if (ncci)
866   {
867     if (a->ncci_plci[ncci] == plci->Id)
868     {
869       if (!plci->appl)
870       {
871         ncci_mapping_bug++;
872         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
873           ncci_mapping_bug, Id));
874       }
875       else
876       {
877         appl = plci->appl;
878         ncci_code = ncci | (((word) a->Id) << 8);
879         for (i = 0; i < appl->MaxBuffer; i++)
880         {
881           if ((appl->DataNCCI[i] == ncci_code)
882            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
883           {
884             appl->DataNCCI[i] = 0;
885           }
886         }
887       }
888     }
889   }
890   else
891   {
892     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
893     {
894       if (a->ncci_plci[ncci] == plci->Id)
895       {
896         if (!plci->appl)
897         {
898           ncci_mapping_bug++;
899           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
900             ncci_mapping_bug, Id));
901         }
902         else
903         {
904           appl = plci->appl;
905           ncci_code = ncci | (((word) a->Id) << 8);
906           for (i = 0; i < appl->MaxBuffer; i++)
907           {
908             if ((appl->DataNCCI[i] == ncci_code)
909              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
910             {
911               appl->DataNCCI[i] = 0;
912             }
913           }
914         }
915       }
916     }
917   }
918 }
919
920
921 static void cleanup_ncci_data (PLCI   *plci, word ncci)
922 {
923   NCCI   *ncci_ptr;
924
925   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
926   {
927     ncci_ptr = &(plci->adapter->ncci[ncci]);
928     if (plci->appl)
929     {
930       while (ncci_ptr->data_pending != 0)
931       {
932         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
933           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
934         (ncci_ptr->data_out)++;
935         if (ncci_ptr->data_out == MAX_DATA_B3)
936           ncci_ptr->data_out = 0;
937         (ncci_ptr->data_pending)--;
938       }
939     }
940     ncci_ptr->data_out = 0;
941     ncci_ptr->data_pending = 0;
942     ncci_ptr->data_ack_out = 0;
943     ncci_ptr->data_ack_pending = 0;
944   }
945 }
946
947
948 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
949 {
950   DIVA_CAPI_ADAPTER   *a;
951   dword Id;
952   word i;
953
954   a = plci->adapter;
955   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
956   if (!preserve_ncci)
957     ncci_free_receive_buffers (plci, ncci);
958   if (ncci)
959   {
960     if (a->ncci_plci[ncci] != plci->Id)
961     {
962       ncci_mapping_bug++;
963       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
964         ncci_mapping_bug, Id, preserve_ncci));
965     }
966     else
967     {
968       cleanup_ncci_data (plci, ncci);
969       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
970         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
971       a->ch_ncci[a->ncci_ch[ncci]] = 0;
972       if (!preserve_ncci)
973       {
974         a->ncci_ch[ncci] = 0;
975         a->ncci_plci[ncci] = 0;
976         a->ncci_state[ncci] = IDLE;
977         i = plci->ncci_ring_list;
978         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
979           i = a->ncci_next[i];
980         if ((i != 0) && (a->ncci_next[i] == ncci))
981         {
982           if (i == ncci)
983             plci->ncci_ring_list = 0;
984           else if (plci->ncci_ring_list == ncci)
985             plci->ncci_ring_list = i;
986           a->ncci_next[i] = a->ncci_next[ncci];
987         }
988         a->ncci_next[ncci] = 0;
989       }
990     }
991   }
992   else
993   {
994     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
995     {
996       if (a->ncci_plci[ncci] == plci->Id)
997       {
998         cleanup_ncci_data (plci, ncci);
999         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
1000           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
1001         a->ch_ncci[a->ncci_ch[ncci]] = 0;
1002         if (!preserve_ncci)
1003         {
1004           a->ncci_ch[ncci] = 0;
1005           a->ncci_plci[ncci] = 0;
1006           a->ncci_state[ncci] = IDLE;
1007           a->ncci_next[ncci] = 0;
1008         }
1009       }
1010     }
1011     if (!preserve_ncci)
1012       plci->ncci_ring_list = 0;
1013   }
1014 }
1015
1016
1017 /*------------------------------------------------------------------*/
1018 /* PLCI remove function                                             */
1019 /*------------------------------------------------------------------*/
1020
1021 static void plci_free_msg_in_queue (PLCI   *plci)
1022 {
1023   word i;
1024
1025   if (plci->appl)
1026   {
1027     i = plci->msg_in_read_pos;
1028     while (i != plci->msg_in_write_pos)
1029     {
1030       if (i == plci->msg_in_wrap_pos)
1031         i = 0;
1032       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1033       {
1034
1035         TransmitBufferFree (plci->appl,
1036           (byte   *)(((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1037
1038       }
1039
1040       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1041         MSG_IN_OVERHEAD + 3) & 0xfffc;
1042
1043     }
1044   }
1045   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1046   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1047   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1048 }
1049
1050
1051 void plci_remove(PLCI   * plci)
1052 {
1053
1054   if(!plci) {
1055     dbug(1,dprintf("plci_remove(no plci)"));
1056     return;
1057   }
1058   init_internal_command_queue (plci);
1059   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1060   if(plci_remove_check(plci))
1061   {
1062     return;
1063   }
1064   if (plci->Sig.Id == 0xff)
1065   {
1066     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1067     if (plci->NL.Id && !plci->nl_remove_id)
1068     {
1069       nl_req_ncci(plci,REMOVE,0);
1070       send_req(plci);
1071     }
1072   }
1073   else
1074   {
1075     if (!plci->sig_remove_id
1076      && (plci->Sig.Id
1077       || (plci->req_in!=plci->req_out)
1078       || (plci->nl_req || plci->sig_req)))
1079     {
1080       sig_req(plci,HANGUP,0);
1081       send_req(plci);
1082     }
1083   }
1084   ncci_remove (plci, 0, FALSE);
1085   plci_free_msg_in_queue (plci);
1086
1087   plci->channels = 0;
1088   plci->appl = 0;
1089   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1090     plci->State = OUTG_DIS_PENDING;
1091 }
1092
1093 /*------------------------------------------------------------------*/
1094 /* Application Group function helpers                               */
1095 /*------------------------------------------------------------------*/
1096
1097 void set_group_ind_mask (PLCI   *plci)
1098 {
1099   word i;
1100
1101   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1102     plci->group_optimization_mask_table[i] = 0xffffffffL;
1103 }
1104
1105 void set_group_ind_mask_bit (PLCI   *plci, word b)
1106 {
1107   plci->group_optimization_mask_table[b >> 5] |= (1L << (b & 0x1f));
1108 }
1109
1110 void clear_group_ind_mask_bit (PLCI   *plci, word b)
1111 {
1112   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1113 }
1114
1115 byte test_group_ind_mask_bit (PLCI   *plci, word b)
1116 {
1117   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1118 }
1119
1120 /*------------------------------------------------------------------*/
1121 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1122 /*------------------------------------------------------------------*/
1123
1124 void clear_c_ind_mask (PLCI   *plci)
1125 {
1126   word i;
1127
1128   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1129     plci->c_ind_mask_table[i] = 0;
1130 }
1131
1132 byte c_ind_mask_empty (PLCI   *plci)
1133 {
1134   word i;
1135
1136   i = 0;
1137   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1138     i++;
1139   return (i == C_IND_MASK_DWORDS);
1140 }
1141
1142 void set_c_ind_mask_bit (PLCI   *plci, word b)
1143 {
1144   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1145 }
1146
1147 void clear_c_ind_mask_bit (PLCI   *plci, word b)
1148 {
1149   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1150 }
1151
1152 byte test_c_ind_mask_bit (PLCI   *plci, word b)
1153 {
1154   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1155 }
1156
1157 void dump_c_ind_mask (PLCI   *plci)
1158 {
1159 static char hex_digit_table[0x10] =
1160   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1161   word i, j, k;
1162   dword d;
1163     char *p;
1164     char buf[40];
1165
1166   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1167   {
1168     p = buf + 36;
1169     *p = '\0';
1170     for (j = 0; j < 4; j++)
1171     {
1172       if (i+j < C_IND_MASK_DWORDS)
1173       {
1174         d = plci->c_ind_mask_table[i+j];
1175         for (k = 0; k < 8; k++)
1176         {
1177           *(--p) = hex_digit_table[d & 0xf];
1178           d >>= 4;
1179         }
1180       }
1181       else if (i != 0)
1182       {
1183         for (k = 0; k < 8; k++)
1184           *(--p) = ' ';
1185       }
1186       *(--p) = ' ';
1187     }
1188     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1189   }
1190 }
1191
1192
1193
1194
1195
1196 #define dump_plcis(a)
1197
1198
1199
1200 /*------------------------------------------------------------------*/
1201 /* translation function for each message                            */
1202 /*------------------------------------------------------------------*/
1203
1204 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1205 {
1206   word ch;
1207   word i;
1208   word Info;
1209   word CIP;
1210   byte LinkLayer;
1211   API_PARSE * ai;
1212   API_PARSE * bp;
1213     API_PARSE ai_parms[5];
1214   word channel = 0;
1215   dword ch_mask;
1216   byte m;
1217   static byte esc_chi[35] = {0x02,0x18,0x01};
1218   static byte lli[2] = {0x01,0x00};
1219   byte noCh = 0;
1220   word dir = 0;
1221   byte   *p_chi = "";
1222
1223   for(i=0;i<5;i++) ai_parms[i].length = 0;
1224
1225   dbug(1,dprintf("connect_req(%d)",parms->length));
1226   Info = _WRONG_IDENTIFIER;
1227   if(a)
1228   {
1229     if(a->adapter_disabled)
1230     {
1231       dbug(1,dprintf("adapter disabled"));
1232       Id = ((word)1<<8)|a->Id;
1233       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1234       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1235       return FALSE;
1236     }
1237     Info = _OUT_OF_PLCI;
1238     if((i=get_plci(a)))
1239     {
1240       Info = 0;
1241       plci = &a->plci[i-1];
1242       plci->appl = appl;
1243       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1244       /* check 'external controller' bit for codec support */
1245       if(Id & EXT_CONTROLLER)
1246       {
1247         if(AdvCodecSupport(a, plci, appl, 0) )
1248         {
1249           plci->Id = 0;
1250           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1251           return 2;
1252         }
1253       }
1254       ai = &parms[9];
1255       bp = &parms[5];
1256       ch = 0;
1257       if(bp->length)LinkLayer = bp->info[3];
1258       else LinkLayer = 0;
1259       if(ai->length)
1260       {
1261         ch=0xffff;
1262         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1263         {
1264           ch = 0;
1265           if(ai_parms[0].length)
1266           {
1267             ch = READ_WORD(ai_parms[0].info+1);
1268             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1269             if(ch==4) /* explizit CHI in message */
1270             {
1271               /* check length of B-CH struct */
1272               if((ai_parms[0].info)[3]>=1)
1273               {
1274                 if((ai_parms[0].info)[4]==CHI)
1275                 {
1276                   p_chi = &((ai_parms[0].info)[5]);
1277                 }
1278                 else
1279                 {
1280                   p_chi = &((ai_parms[0].info)[3]);
1281                 }
1282                 if(p_chi[0]>35) /* check length of channel ID */
1283                 {
1284                   Info = _WRONG_MESSAGE_FORMAT;    
1285                 }
1286               }
1287               else Info = _WRONG_MESSAGE_FORMAT;    
1288             }
1289
1290             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1291             {
1292               dir = READ_WORD(ai_parms[0].info+3);
1293               ch_mask = 0;
1294               m = 0x3f;
1295               for(i=0; i+5<=ai_parms[0].length; i++)
1296               {
1297                 if(ai_parms[0].info[i+5]!=0)
1298                 {
1299                   if((ai_parms[0].info[i+5] | m) != 0xff)
1300                     Info = _WRONG_MESSAGE_FORMAT;
1301                   else
1302                   {
1303                     if (ch_mask == 0)
1304                       channel = i;
1305                     ch_mask |= 1L << i;
1306                   }
1307                 }
1308                 m = 0;
1309               }
1310               if (ch_mask == 0)
1311                 Info = _WRONG_MESSAGE_FORMAT;
1312               if (!Info)
1313               {
1314                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1315                 {
1316                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1317                   for(i=0; i+5<=ai_parms[0].length; i++)
1318                     esc_chi[i+3] = ai_parms[0].info[i+5];
1319                 }
1320                 else
1321                   esc_chi[0] = 2;
1322                 esc_chi[2] = (byte)channel;
1323                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1324                 add_p(plci,LLI,lli);
1325                 add_p(plci,ESC,esc_chi);
1326                 plci->State = LOCAL_CONNECT;
1327                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1328               }
1329             }
1330           }
1331         }
1332         else  Info = _WRONG_MESSAGE_FORMAT;
1333       }
1334
1335       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1336       plci->command = _CONNECT_R;
1337       plci->number = Number;
1338       /* x.31 or D-ch free SAPI in LinkLayer? */
1339       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = TRUE;
1340       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1341       {
1342         /* B-channel used for B3 connections (ch==0), or no B channel    */
1343         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1344         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1345         else     Info = add_b1(plci,&parms[5],ch,0); 
1346         add_s(plci,OAD,&parms[2]);
1347         add_s(plci,OSA,&parms[4]);
1348         add_s(plci,BC,&parms[6]);
1349         add_s(plci,LLC,&parms[7]);
1350         add_s(plci,HLC,&parms[8]);
1351         CIP = READ_WORD(parms[0].info);
1352         if (a->Info_Mask[appl->Id-1] & 0x200)
1353         {
1354           /* early B3 connect (CIP mask bit 9) no release after a disc */
1355           add_p(plci,LLI,"\x01\x01");
1356         }
1357         if(READ_WORD(parms[0].info)<29) {
1358           add_p(plci,BC,cip_bc[READ_WORD(parms[0].info)][a->u_law]);
1359           add_p(plci,HLC,cip_hlc[READ_WORD(parms[0].info)]);
1360         }
1361         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1362         sig_req(plci,ASSIGN,DSIG_ID);
1363       }
1364       else if(ch==1) {
1365
1366         /* D-Channel used for B3 connections */
1367         plci->Sig.Id = 0xff;
1368         Info = 0;
1369       }
1370
1371       if(!Info && ch!=2 && !noCh ) {
1372         Info = add_b23(plci,&parms[5]);
1373         if(!Info) {
1374           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1375         }
1376       }
1377
1378       if(!Info)
1379       {
1380         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1381         {
1382           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1383           {
1384             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1385             plci->spoofed_msg = CALL_REQ;
1386             plci->internal_command = BLOCK_PLCI;
1387             plci->command = 0;
1388             dbug(1,dprintf("Spoof"));
1389             send_req(plci);
1390             return FALSE;
1391           }
1392           if(ch==4)add_p(plci,CHI,p_chi);
1393           add_s(plci,CPN,&parms[1]);
1394           add_s(plci,DSA,&parms[3]);
1395           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1396           add_ai(plci,&parms[9]);
1397           if(!dir)sig_req(plci,CALL_REQ,0);
1398           else
1399           {
1400             plci->command = PERM_LIST_REQ;
1401             plci->appl = appl;
1402             sig_req(plci,LISTEN_REQ,0);
1403             send_req(plci);
1404             return FALSE;
1405           }
1406         }
1407         send_req(plci);
1408         return FALSE;
1409       }
1410       plci->Id = 0;
1411     }
1412   }
1413   sendf(appl,
1414         _CONNECT_R|CONFIRM,
1415         Id,
1416         Number,
1417         "w",Info);
1418   return 2;
1419 }
1420
1421 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1422 {
1423   word i, Info;
1424   word Reject;
1425   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1426   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1427   API_PARSE * ai;
1428     API_PARSE ai_parms[5];
1429   word ch=0;
1430
1431   if(!plci) {
1432     dbug(1,dprintf("connect_res(no plci)"));
1433     return 0;  /* no plci, no send */
1434   }
1435
1436   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1437   for(i=0;i<5;i++) ai_parms[i].length = 0;
1438   ai = &parms[5];
1439   dbug(1,dprintf("ai->length=%d",ai->length));
1440
1441   if(ai->length)
1442   {
1443     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1444     {
1445       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,READ_WORD(ai_parms[0].info+1)));
1446       ch = 0;
1447       if(ai_parms[0].length)
1448       {
1449         ch = READ_WORD(ai_parms[0].info+1);
1450         dbug(1,dprintf("BCH-I=0x%x",ch));
1451       }
1452     }
1453   }
1454
1455   if(plci->State==INC_CON_CONNECTED_ALERT)
1456   {
1457     dbug(1,dprintf("Connected Alert Call_Res"));
1458     if (a->Info_Mask[appl->Id-1] & 0x200)
1459     {
1460     /* early B3 connect (CIP mask bit 9) no release after a disc */
1461       add_p(plci,LLI,"\x01\x01");
1462     }
1463     add_s(plci, CONN_NR, &parms[2]);
1464     add_s(plci, LLC, &parms[4]);
1465     add_ai(plci, &parms[5]);
1466     plci->State = INC_CON_ACCEPT;
1467     sig_req(plci, CALL_RES,0);
1468     return 1;
1469   }
1470   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1471     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1472     dump_c_ind_mask (plci);
1473     Reject = READ_WORD(parms[0].info);
1474     dbug(1,dprintf("Reject=0x%x",Reject));
1475     if(Reject) 
1476     {
1477       if(c_ind_mask_empty (plci)) 
1478       {
1479         if((Reject&0xff00)==0x3400) 
1480         {
1481           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1482           add_p(plci,ESC,esc_t);
1483           add_ai(plci, &parms[5]);
1484           sig_req(plci,REJECT,0);
1485         }      
1486         else if(Reject==1 || Reject>9) 
1487         {
1488           add_ai(plci, &parms[5]);
1489           sig_req(plci,HANGUP,0);
1490         }
1491         else 
1492         {
1493           esc_t[2] = cau_t[(Reject&0x000f)];
1494           add_p(plci,ESC,esc_t);
1495           add_ai(plci, &parms[5]);
1496           sig_req(plci,REJECT,0);
1497         }
1498         plci->appl = appl;
1499       }
1500       else 
1501       {
1502         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1503       }
1504     }
1505     else {
1506       plci->appl = appl;
1507       if(Id & EXT_CONTROLLER){
1508         if(AdvCodecSupport(a, plci, appl, 0)){
1509           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1510           sig_req(plci,HANGUP,0);
1511           return 1;
1512         }
1513         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1514         {
1515           Info = add_b23(plci, &parms[1]);
1516           if (Info)
1517           {
1518             dbug(1,dprintf("connect_res(error from add_b23)"));
1519             sig_req(plci,HANGUP,0);
1520             return 1;
1521           }
1522           if(plci->adv_nl)
1523           {
1524             nl_req_ncci(plci, ASSIGN, 0);
1525           }
1526         }
1527       }
1528       else
1529       {
1530         plci->tel = 0;
1531         if(ch!=2)
1532         {
1533           Info = add_b23(plci, &parms[1]);
1534           if (Info)
1535           {
1536             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1537             sig_req(plci,HANGUP,0);
1538             return 1;
1539           }
1540         }
1541         nl_req_ncci(plci, ASSIGN, 0);
1542       }
1543
1544       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1545       {
1546         api_save_msg(parms, "wsssss", &plci->saved_msg);
1547         plci->spoofed_msg = CALL_RES;
1548         plci->internal_command = BLOCK_PLCI;
1549         plci->command = 0;
1550         dbug(1,dprintf("Spoof"));
1551       }
1552       else
1553       {
1554         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1555         if (a->Info_Mask[appl->Id-1] & 0x200)
1556         {
1557           /* early B3 connect (CIP mask bit 9) no release after a disc */
1558           add_p(plci,LLI,"\x01\x01");
1559         }
1560         add_s(plci, CONN_NR, &parms[2]);
1561         add_s(plci, LLC, &parms[4]);
1562         add_ai(plci, &parms[5]);
1563         plci->State = INC_CON_ACCEPT;
1564         sig_req(plci, CALL_RES,0);
1565       }
1566
1567       for(i=0; i<max_appl; i++) {
1568         if(test_c_ind_mask_bit (plci, i)) {
1569           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1570         }
1571       }
1572     }
1573   }
1574   return 1;
1575 }
1576
1577 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1578 {
1579   dbug(1,dprintf("connect_a_res"));
1580   return FALSE;
1581 }
1582
1583 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1584 {
1585   word Info;
1586   word i;
1587
1588   dbug(1,dprintf("disconnect_req"));
1589
1590   Info = _WRONG_IDENTIFIER;
1591
1592   if(plci)
1593   {
1594     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1595     {
1596       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1597       plci->appl = appl;
1598       for(i=0; i<max_appl; i++)
1599       {
1600         if(test_c_ind_mask_bit (plci, i))
1601           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1602       }
1603       plci->State = OUTG_DIS_PENDING;
1604     }
1605     if(plci->Sig.Id && plci->appl)
1606     {
1607       Info = 0;
1608         if(plci->Sig.Id!=0xff)
1609         {
1610           if(plci->State!=INC_DIS_PENDING)
1611           {
1612             add_ai(plci, &msg[0]);
1613             sig_req(plci,HANGUP,0);
1614             plci->State = OUTG_DIS_PENDING;
1615             return 1;
1616           }
1617         }
1618         else
1619         {
1620           if (plci->NL.Id && !plci->nl_remove_id)
1621           {
1622             mixer_remove (plci);
1623             nl_req_ncci(plci,REMOVE,0);
1624           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1625           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1626           plci->State = INC_DIS_PENDING;
1627           }
1628           return 1;
1629         }
1630       }
1631     }
1632
1633   if(!appl)  return FALSE;
1634   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1635   return FALSE;
1636 }
1637
1638 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1639 {
1640   dbug(1,dprintf("disconnect_res"));
1641   if(plci)
1642   {
1643         /* clear ind mask bit, just in case of collsion of          */
1644         /* DISCONNECT_IND and CONNECT_RES                           */
1645     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1646     ncci_free_receive_buffers (plci, 0);
1647     if(plci_remove_check(plci))
1648     {
1649       return 0;
1650     }
1651     if(plci->State==INC_DIS_PENDING
1652     || plci->State==SUSPENDING) {
1653       if(c_ind_mask_empty (plci)) {
1654         if(plci->State!=SUSPENDING)plci->State = IDLE;
1655         dbug(1,dprintf("chs=%d",plci->channels));
1656         if(!plci->channels) {
1657           plci_remove(plci);
1658         }
1659       }
1660     }
1661   }
1662   return 0;
1663 }
1664
1665 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1666 {
1667   word Info;
1668   byte i;
1669
1670   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1671
1672   Info = _WRONG_IDENTIFIER;
1673   if(a) {
1674     Info = 0;
1675     a->Info_Mask[appl->Id-1] = READ_DWORD(parms[0].info);
1676     a->CIP_Mask[appl->Id-1] = READ_DWORD(parms[1].info);
1677     dbug(1,dprintf("CIP_MASK=0x%lx",READ_DWORD(parms[1].info)));
1678     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1679       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1680     }
1681
1682     /* check if external controller listen and switch listen on or off*/
1683     if(Id&EXT_CONTROLLER && READ_DWORD(parms[1].info)){
1684       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1685         dummy_plci.State = IDLE;
1686         a->codec_listen[appl->Id-1] = &dummy_plci;
1687         a->TelOAD[0] = (byte)(parms[3].length);
1688         for(i=1;parms[3].length>=i && i<22;i++) {
1689           a->TelOAD[i] = parms[3].info[i];
1690         }
1691         a->TelOAD[i] = 0;
1692         a->TelOSA[0] = (byte)(parms[4].length);
1693         for(i=1;parms[4].length>=i && i<22;i++) {
1694           a->TelOSA[i] = parms[4].info[i];
1695         }
1696         a->TelOSA[i] = 0;
1697       }
1698       else Info = 0x2002; /* wrong controller, codec not supported */
1699     }
1700     else{               /* clear listen */
1701       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1702     }
1703   }
1704   sendf(appl,
1705         _LISTEN_R|CONFIRM,
1706         Id,
1707         Number,
1708         "w",Info);
1709
1710   if (a) listen_check(a);
1711   return FALSE;
1712 }
1713
1714 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1715 {
1716   word i;
1717   API_PARSE * ai;
1718   PLCI   * rc_plci = 0;
1719     API_PARSE ai_parms[5];
1720   word Info = 0;
1721
1722   dbug(1,dprintf("info_req"));
1723   for(i=0;i<5;i++) ai_parms[i].length = 0;
1724
1725   ai = &msg[1];
1726
1727   if(ai->length)
1728   {
1729     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1730     {
1731       dbug(1,dprintf("AddInfo wrong"));
1732       Info = _WRONG_MESSAGE_FORMAT;
1733     }
1734   }
1735   if(!a) Info = _WRONG_STATE;
1736
1737   if(!Info && plci)
1738   {                /* no fac, with CPN, or KEY */
1739     rc_plci = plci;
1740     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1741     {
1742       /* overlap sending option */
1743       dbug(1,dprintf("OvlSnd"));
1744       add_s(plci,CPN,&msg[0]);
1745       add_s(plci,KEY,&ai_parms[1]);
1746       sig_req(plci,INFO_REQ,0);
1747       send_req(plci);
1748       return FALSE;
1749     }
1750
1751     if(plci->State && ai_parms[2].length)
1752     {
1753       /* User_Info option */
1754       dbug(1,dprintf("UUI"));
1755       add_s(plci,UUI,&ai_parms[2]);
1756       sig_req(plci,USER_DATA,0);
1757     }
1758     else if(plci->State && ai_parms[3].length)
1759     {
1760       /* Facility option */
1761       dbug(1,dprintf("FAC"));
1762       add_s(plci,CPN,&msg[0]);
1763       add_ai(plci, &msg[1]);
1764       sig_req(plci,FACILITY_REQ,0);
1765     }
1766     else
1767     {
1768       Info = _WRONG_STATE;
1769     }
1770   }
1771   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1772   {
1773     /* NCR_Facility option -> send UUI and Keypad too */
1774     dbug(1,dprintf("NCR_FAC"));
1775     if((i=get_plci(a)))
1776     {
1777       rc_plci = &a->plci[i-1];
1778       appl->NullCREnable  = TRUE;
1779       rc_plci->internal_command = C_NCR_FAC_REQ;
1780       rc_plci->appl = appl;
1781       add_p(rc_plci,CAI,"\x01\x80");
1782       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1783       sig_req(rc_plci,ASSIGN,DSIG_ID);
1784       send_req(rc_plci);
1785     }
1786     else
1787     {
1788       Info = _OUT_OF_PLCI;
1789     }
1790
1791     if(!Info)
1792     {
1793       add_s(rc_plci,CPN,&msg[0]);
1794       add_ai(rc_plci, &msg[1]);
1795       sig_req(rc_plci,NCR_FACILITY,0);
1796       send_req(rc_plci);
1797       return FALSE;
1798      /* for application controlled supplementary services    */
1799     }
1800   }
1801
1802   if (!rc_plci)
1803   {
1804     Info = _WRONG_MESSAGE_FORMAT;
1805   }
1806
1807   if(!Info)
1808   {
1809     send_req(rc_plci);
1810   }
1811   else
1812   {  /* appl is not assigned to a PLCI or error condition */
1813     dbug(1,dprintf("localInfoCon"));
1814     sendf(appl,
1815           _INFO_R|CONFIRM,
1816           Id,
1817           Number,
1818           "w",Info);
1819   }
1820   return FALSE;
1821 }
1822
1823 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1824 {
1825   dbug(1,dprintf("info_res"));
1826   return FALSE;
1827 }
1828
1829 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1830 {
1831   word Info;
1832   byte ret;
1833
1834   dbug(1,dprintf("alert_req"));
1835
1836   Info = _WRONG_IDENTIFIER;
1837   ret = FALSE;
1838   if(plci) {
1839     Info = _ALERT_IGNORED;
1840     if(plci->State!=INC_CON_ALERT) {
1841       Info = _WRONG_STATE;
1842       if(plci->State==INC_CON_PENDING) {
1843         Info = 0;
1844         plci->State=INC_CON_ALERT;
1845         add_ai(plci, &msg[0]);
1846         sig_req(plci,CALL_ALERT,0);
1847         ret = 1;
1848       }
1849     }
1850   }
1851   sendf(appl,
1852         _ALERT_R|CONFIRM,
1853         Id,
1854         Number,
1855         "w",Info);
1856   return ret;
1857 }
1858
1859 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1860 {
1861   word Info = 0;
1862   word i    = 0;
1863
1864   word selector;
1865   word SSreq;
1866   long relatedPLCIvalue;
1867   DIVA_CAPI_ADAPTER   * relatedadapter;
1868   byte * SSparms  = "";
1869     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1870     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1871   API_PARSE * parms;
1872     API_PARSE ss_parms[11];
1873   PLCI   *rplci;
1874     byte cai[15];
1875   dword d;
1876     API_PARSE dummy;
1877
1878   dbug(1,dprintf("facility_req"));
1879   for(i=0;i<9;i++) ss_parms[i].length = 0;
1880
1881   parms = &msg[1];
1882
1883   if(!a)
1884   {
1885     dbug(1,dprintf("wrong Ctrl"));
1886     Info = _WRONG_IDENTIFIER;
1887   }
1888
1889   selector = READ_WORD(msg[0].info);
1890
1891   if(!Info)
1892   {
1893     switch(selector)
1894     {
1895       case SELECTOR_HANDSET:
1896         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1897         break;
1898
1899       case SELECTOR_SU_SERV:
1900         if(!msg[1].length)
1901         {
1902           Info = _WRONG_MESSAGE_FORMAT;
1903           break;
1904         }
1905         SSreq = READ_WORD(&(msg[1].info[1]));
1906         WRITE_WORD(&RCparms[1],SSreq);
1907         SSparms = RCparms;
1908         switch(SSreq)
1909         {
1910           case S_GET_SUPPORTED_SERVICES:
1911             if((i=get_plci(a)))
1912             {
1913               rplci = &a->plci[i-1];
1914               rplci->appl = appl;
1915               add_p(rplci,CAI,"\x01\x80");
1916               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1917               sig_req(rplci,ASSIGN,DSIG_ID);
1918               send_req(rplci);
1919             }
1920             else
1921             {
1922               WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1923               SSparms = (byte *)SSstruct;
1924               break;
1925             }
1926             rplci->internal_command = GETSERV_REQ_PEND;
1927             rplci->number = Number;
1928             rplci->appl = appl;
1929             sig_req(rplci,S_SUPPORTED,0);
1930             send_req(rplci);
1931             return FALSE;
1932             break;
1933
1934           case S_LISTEN:
1935             if(parms->length==7)
1936             {
1937               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1938               {
1939                 dbug(1,dprintf("format wrong"));
1940                 Info = _WRONG_MESSAGE_FORMAT;
1941                 break;
1942               }
1943             }
1944             else
1945             {
1946               Info = _WRONG_MESSAGE_FORMAT;
1947               break;
1948             }
1949             a->Notification_Mask[appl->Id-1] = READ_DWORD(ss_parms[2].info);
1950             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1951             {
1952               if((i=get_plci(a)))
1953               {
1954                 rplci = &a->plci[i-1];
1955                 rplci->appl = appl;
1956                 add_p(rplci,CAI,"\x01\x80");
1957                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1958                 sig_req(rplci,ASSIGN,DSIG_ID);
1959                 send_req(rplci);
1960               }
1961               else
1962               {
1963                 break;
1964               }
1965               rplci->internal_command = GET_MWI_STATE;
1966               rplci->number = Number;
1967               sig_req(rplci,MWI_POLL,0);
1968               send_req(rplci);
1969             }
1970             break;
1971
1972           case S_HOLD:
1973             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1974             if(plci && plci->State && plci->SuppState==IDLE)
1975             {
1976               plci->SuppState = HOLD_REQUEST;
1977               plci->command = C_HOLD_REQ;
1978               add_s(plci,CAI,&ss_parms[1]);
1979               sig_req(plci,CALL_HOLD,0);
1980               send_req(plci);
1981               return FALSE;
1982             }
1983             else Info = 0x3010;                    /* wrong state           */
1984             break;
1985           case S_RETRIEVE:
1986             if(plci && plci->State && plci->SuppState==CALL_HELD)
1987             {
1988               if(Id & EXT_CONTROLLER)
1989               {
1990                 if(AdvCodecSupport(a, plci, appl, 0))
1991                 {
1992                   Info = 0x3010;                    /* wrong state           */
1993                   break;
1994                 }
1995               }
1996               else plci->tel = 0;
1997
1998               plci->SuppState = RETRIEVE_REQUEST;
1999               plci->command = C_RETRIEVE_REQ;
2000               if(plci->spoofed_msg==SPOOFING_REQUIRED)
2001               {
2002                 plci->spoofed_msg = CALL_RETRIEVE;
2003                 plci->internal_command = BLOCK_PLCI;
2004                 plci->command = 0;
2005                 dbug(1,dprintf("Spoof"));
2006                 return FALSE;
2007               }
2008               else
2009               {
2010                 sig_req(plci,CALL_RETRIEVE,0);
2011                 send_req(plci);
2012                 return FALSE;
2013               }
2014             }
2015             else Info = 0x3010;                    /* wrong state           */
2016             break;
2017           case S_SUSPEND:
2018             if(parms->length)
2019             {
2020               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2021               {
2022                 dbug(1,dprintf("format wrong"));
2023                 Info = _WRONG_MESSAGE_FORMAT;
2024                 break;
2025               }
2026             }
2027             if(plci && plci->State)
2028             {
2029               add_s(plci,CAI,&ss_parms[2]);
2030               plci->command = SUSPEND_REQ;
2031               sig_req(plci,SUSPEND,0);
2032               plci->State = SUSPENDING;
2033               send_req(plci);
2034             }
2035             else Info = 0x3010;                    /* wrong state           */
2036             break;
2037
2038           case S_RESUME:
2039             if(!(i=get_plci(a)) )
2040             {
2041               Info = _OUT_OF_PLCI;
2042               break;
2043             }
2044             rplci = &a->plci[i-1];
2045             rplci->appl = appl;
2046             rplci->number = Number;
2047             rplci->tel = 0;
2048             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2049             /* check 'external controller' bit for codec support */
2050             if(Id & EXT_CONTROLLER)
2051             {
2052               if(AdvCodecSupport(a, rplci, appl, 0) )
2053               {
2054                 rplci->Id = 0;
2055                 Info = 0x300A;
2056                 break;
2057               }
2058             }
2059             if(parms->length)
2060             {
2061               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2062               {
2063                 dbug(1,dprintf("format wrong"));
2064                 rplci->Id = 0;
2065                 Info = _WRONG_MESSAGE_FORMAT;
2066                 break;
2067               }
2068             }
2069             dummy.length = 0;
2070             dummy.info = "\x00";
2071             add_b1(rplci, &dummy, 0, 0);
2072             if (a->Info_Mask[appl->Id-1] & 0x200)
2073             {
2074               /* early B3 connect (CIP mask bit 9) no release after a disc */
2075               add_p(rplci,LLI,"\x01\x01");
2076             }
2077             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2078             sig_req(rplci,ASSIGN,DSIG_ID);
2079             send_req(rplci);
2080             add_s(rplci,CAI,&ss_parms[2]);
2081             rplci->command = RESUME_REQ;
2082             sig_req(rplci,RESUME,0);
2083             rplci->State = RESUMING;
2084             send_req(rplci);
2085             break;
2086
2087           case S_CONF_BEGIN: /* Request */
2088           case S_CONF_DROP:
2089           case S_CONF_ISOLATE:
2090           case S_CONF_REATTACH:
2091             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2092             {
2093               dbug(1,dprintf("format wrong"));
2094               Info = _WRONG_MESSAGE_FORMAT;
2095               break;
2096             }
2097             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2098             {
2099               d = READ_DWORD(ss_parms[2].info);     
2100               if(d>=0x80)
2101               {
2102                 dbug(1,dprintf("format wrong"));
2103                 Info = _WRONG_MESSAGE_FORMAT;
2104                 break;
2105               }
2106               plci->ptyState = (byte)SSreq;
2107               plci->command = 0;
2108               cai[0] = 2;
2109               switch(SSreq)
2110               {
2111               case S_CONF_BEGIN:
2112                   cai[1] = CONF_BEGIN;
2113                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2114                   break;
2115               case S_CONF_DROP:
2116                   cai[1] = CONF_DROP;
2117                   plci->internal_command = CONF_DROP_REQ_PEND;
2118                   break;
2119               case S_CONF_ISOLATE:
2120                   cai[1] = CONF_ISOLATE;
2121                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2122                   break;
2123               case S_CONF_REATTACH:
2124                   cai[1] = CONF_REATTACH;
2125                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2126                   break;
2127               }
2128               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2129               add_p(plci,CAI,cai);
2130               sig_req(plci,S_SERVICE,0);
2131               send_req(plci);
2132               return FALSE;
2133             }
2134             else Info = 0x3010;                    /* wrong state           */
2135             break;
2136
2137           case S_ECT:
2138           case S_3PTY_BEGIN:
2139           case S_3PTY_END:
2140           case S_CONF_ADD:
2141             if(parms->length==7)
2142             {
2143               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2144               {
2145                 dbug(1,dprintf("format wrong"));
2146                 Info = _WRONG_MESSAGE_FORMAT;
2147                 break;
2148               }
2149             }
2150             else if(parms->length==8) /* workaround for the T-View-S */
2151             {
2152               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2153               {
2154                 dbug(1,dprintf("format wrong"));
2155                 Info = _WRONG_MESSAGE_FORMAT;
2156                 break;
2157               }
2158             }
2159             else
2160             {
2161               Info = _WRONG_MESSAGE_FORMAT;
2162               break;
2163             }
2164             if(!msg[1].length)
2165             {
2166               Info = _WRONG_MESSAGE_FORMAT;
2167               break;
2168             }
2169             if (!plci)
2170             {
2171               Info = _WRONG_IDENTIFIER;
2172               break;
2173             }
2174             relatedPLCIvalue = READ_DWORD(ss_parms[2].info);
2175             relatedPLCIvalue &= 0x0000FFFF;
2176             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2177             /* controller starts with 0 up to (max_adapter - 1) */
2178             if (((relatedPLCIvalue & 0x7f) == 0)
2179              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2180              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2181             {
2182               if(SSreq==S_3PTY_END)
2183               {
2184                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2185                 rplci = plci;
2186               }
2187               else
2188               {
2189                 Info = 0x3010;                    /* wrong state           */
2190                 break;
2191               }
2192             }
2193             else
2194             {  
2195               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2196               relatedPLCIvalue >>=8;
2197               /* find PLCI PTR*/
2198               for(i=0,rplci=0;i<relatedadapter->max_plci;i++)
2199               {
2200                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2201                 {
2202                   rplci = &relatedadapter->plci[i];
2203                 }
2204               }
2205               if(!rplci || !relatedPLCIvalue)
2206               {
2207                 if(SSreq==S_3PTY_END)
2208                 {
2209                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2210                   rplci = plci;
2211                 }
2212                 else
2213                 {
2214                   Info = 0x3010;                    /* wrong state           */
2215                   break;
2216                 }
2217               }
2218             }
2219 /*
2220             dbug(1,dprintf("rplci:%x",rplci));
2221             dbug(1,dprintf("plci:%x",plci));
2222             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2223             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2224             dbug(1,dprintf("SSreq:%x",SSreq));
2225             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2226             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2227             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2228 */
2229             /* send PTY/ECT req, cannot check all states because of US stuff */
2230             if( !rplci->internal_command && rplci->appl )
2231             {
2232               plci->command = 0;
2233               rplci->relatedPTYPLCI = plci;
2234               plci->relatedPTYPLCI = rplci;
2235               rplci->ptyState = (byte)SSreq;
2236               if(SSreq==S_ECT)
2237               {
2238                 rplci->internal_command = ECT_REQ_PEND;
2239                 cai[1] = ECT_EXECUTE;
2240
2241                 rplci->vswitchstate=0;
2242                 rplci->vsprot=0;
2243                 rplci->vsprotdialect=0;
2244                 plci->vswitchstate=0;
2245                 plci->vsprot=0;
2246                 plci->vsprotdialect=0;
2247
2248               }
2249               else if(SSreq==S_CONF_ADD)
2250               {
2251                 rplci->internal_command = CONF_ADD_REQ_PEND;
2252                 cai[1] = CONF_ADD;
2253               }
2254               else
2255               {
2256                 rplci->internal_command = PTY_REQ_PEND;
2257                 cai[1] = (byte)(SSreq-3);
2258               }
2259               rplci->number = Number;
2260               if(plci!=rplci) /* explicit invocation */
2261               {
2262                 cai[0] = 2;
2263                 cai[2] = plci->Sig.Id;
2264                 dbug(1,dprintf("explicit invocation"));
2265               }
2266               else
2267               {
2268                 dbug(1,dprintf("implicit invocation"));
2269                 cai[0] = 1;
2270               }
2271               add_p(rplci,CAI,cai);
2272               sig_req(rplci,S_SERVICE,0);
2273               send_req(rplci);
2274               return FALSE;
2275             }
2276             else
2277             {
2278               dbug(0,dprintf("Wrong line"));
2279               Info = 0x3010;                    /* wrong state           */
2280               break;
2281             }
2282             break;
2283
2284           case S_CALL_DEFLECTION:
2285             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2286             {
2287               dbug(1,dprintf("format wrong"));
2288               Info = _WRONG_MESSAGE_FORMAT;
2289               break;
2290             }
2291             if (!plci)
2292             {
2293               Info = _WRONG_IDENTIFIER;
2294               break;
2295             }
2296             /* reuse unused screening indicator */
2297             ss_parms[3].info[3] = (byte)READ_WORD(&(ss_parms[2].info[0]));
2298             plci->command = 0;
2299             plci->internal_command = CD_REQ_PEND;
2300             appl->CDEnable = TRUE;
2301             cai[0] = 1;
2302             cai[1] = CALL_DEFLECTION;
2303             add_p(plci,CAI,cai);
2304             add_p(plci,CPN,ss_parms[3].info);
2305             sig_req(plci,S_SERVICE,0);
2306             send_req(plci);
2307             return FALSE;
2308             break;
2309
2310           case S_CALL_FORWARDING_START:
2311             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2312             {
2313               dbug(1,dprintf("format wrong"));
2314               Info = _WRONG_MESSAGE_FORMAT;
2315               break;
2316             }
2317
2318             if((i=get_plci(a)))
2319             {
2320               rplci = &a->plci[i-1];
2321               rplci->appl = appl;
2322               add_p(rplci,CAI,"\x01\x80");
2323               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2324               sig_req(rplci,ASSIGN,DSIG_ID);
2325               send_req(rplci);
2326             }
2327             else
2328             {
2329               Info = _OUT_OF_PLCI;
2330               break;
2331             }
2332
2333             /* reuse unused screening indicator */
2334             rplci->internal_command = CF_START_PEND;
2335             rplci->appl = appl;
2336             rplci->number = Number;
2337             appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0]));
2338             cai[0] = 2;
2339             cai[1] = 0x70|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
2340             cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2341             add_p(rplci,CAI,cai);
2342             add_p(rplci,OAD,ss_parms[5].info);
2343             add_p(rplci,CPN,ss_parms[6].info);
2344             sig_req(rplci,S_SERVICE,0);
2345             send_req(rplci);
2346             return FALSE;
2347             break;
2348
2349           case S_INTERROGATE_DIVERSION:
2350           case S_INTERROGATE_NUMBERS:
2351           case S_CALL_FORWARDING_STOP:
2352           case S_CCBS_REQUEST:
2353           case S_CCBS_DEACTIVATE:
2354           case S_CCBS_INTERROGATE:
2355             switch(SSreq)
2356             {
2357             case S_INTERROGATE_NUMBERS:
2358                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2359                 {
2360                   dbug(0,dprintf("format wrong"));
2361                   Info = _WRONG_MESSAGE_FORMAT;
2362                 }
2363                 break;
2364             case S_CCBS_REQUEST:
2365             case S_CCBS_DEACTIVATE:
2366                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2367                 {
2368                   dbug(0,dprintf("format wrong"));
2369                   Info = _WRONG_MESSAGE_FORMAT;
2370                 }
2371                 break;
2372             case S_CCBS_INTERROGATE:
2373                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2374                 {
2375                   dbug(0,dprintf("format wrong"));
2376                   Info = _WRONG_MESSAGE_FORMAT;
2377                 }
2378                 break;
2379             default:
2380             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2381             {
2382               dbug(0,dprintf("format wrong"));
2383               Info = _WRONG_MESSAGE_FORMAT;
2384               break;
2385             }
2386                 break;
2387             }
2388
2389             if(Info) break;
2390             if((i=get_plci(a)))
2391             {
2392               rplci = &a->plci[i-1];
2393               switch(SSreq)
2394               {
2395                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2396                   cai[1] = 0x60|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
2397                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2398                   break;
2399                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2400                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2401                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2402                   break;
2403                 case S_CALL_FORWARDING_STOP:
2404                   rplci->internal_command = CF_STOP_PEND;
2405                   cai[1] = 0x80|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
2406                   break;
2407                 case S_CCBS_REQUEST:
2408                   cai[1] = CCBS_REQUEST;
2409                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2410                   break;
2411                 case S_CCBS_DEACTIVATE:
2412                   cai[1] = CCBS_DEACTIVATE;
2413                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2414                   break;
2415                 case S_CCBS_INTERROGATE:
2416                   cai[1] = CCBS_INTERROGATE;
2417                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2418                   break;
2419                 default:
2420                   cai[1] = 0;
2421                 break;
2422               }
2423               rplci->appl = appl;
2424               rplci->number = Number;
2425               add_p(rplci,CAI,"\x01\x80");
2426               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2427               sig_req(rplci,ASSIGN,DSIG_ID);
2428               send_req(rplci);
2429             }
2430             else
2431             {
2432               Info = _OUT_OF_PLCI;
2433               break;
2434             }
2435
2436             appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0]));
2437             switch(SSreq)
2438             {
2439             case S_INTERROGATE_NUMBERS:
2440                 cai[0] = 1;
2441                 add_p(rplci,CAI,cai);
2442                 break;
2443             case S_CCBS_REQUEST:
2444             case S_CCBS_DEACTIVATE:
2445                 cai[0] = 3;
2446                 WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0])));
2447                 add_p(rplci,CAI,cai);
2448                 break;
2449             case S_CCBS_INTERROGATE:
2450                 cai[0] = 3;
2451                 WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0])));
2452                 add_p(rplci,CAI,cai);
2453                 add_p(rplci,OAD,ss_parms[4].info);
2454                 break;
2455             default:
2456             cai[0] = 2;
2457             cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2458             add_p(rplci,CAI,cai);
2459             add_p(rplci,OAD,ss_parms[5].info);
2460                 break;
2461             }
2462                         
2463             sig_req(rplci,S_SERVICE,0);
2464             send_req(rplci);
2465             return FALSE;
2466             break;
2467
2468           case S_MWI_ACTIVATE:
2469             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2470             {
2471               dbug(1,dprintf("format wrong"));
2472               Info = _WRONG_MESSAGE_FORMAT;
2473               break;
2474             }
2475             if(!plci)
2476             {                               
2477               if((i=get_plci(a)))
2478               {
2479                 rplci = &a->plci[i-1];
2480                 rplci->appl = appl;
2481                 rplci->cr_enquiry=TRUE;
2482                 add_p(rplci,CAI,"\x01\x80");
2483                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2484                 sig_req(rplci,ASSIGN,DSIG_ID);
2485                 send_req(rplci);
2486               }
2487               else
2488               {
2489                 Info = _OUT_OF_PLCI;
2490                 break;
2491               }
2492             }
2493             else
2494             {
2495               rplci = plci;
2496               rplci->cr_enquiry=FALSE;
2497             }
2498
2499             rplci->command = 0;
2500             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2501             rplci->appl = appl;
2502             rplci->number = Number;
2503
2504             cai[0] = 13;
2505             cai[1] = ACTIVATION_MWI; /* Function */
2506             WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2507             WRITE_DWORD(&cai[4],READ_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2508             WRITE_WORD(&cai[8],READ_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2509             WRITE_WORD(&cai[10],READ_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2510             WRITE_WORD(&cai[12],READ_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2511             add_p(rplci,CAI,cai);
2512             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2513             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2514             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2515             add_p(rplci,UID,ss_parms[10].info); /* Time */
2516             sig_req(rplci,S_SERVICE,0);
2517             send_req(rplci);
2518             return FALSE;
2519
2520           case S_MWI_DEACTIVATE:
2521             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2522             {
2523               dbug(1,dprintf("format wrong"));
2524               Info = _WRONG_MESSAGE_FORMAT;
2525               break;
2526             }
2527             if(!plci)
2528             {                               
2529               if((i=get_plci(a)))
2530               {
2531                 rplci = &a->plci[i-1];
2532                 rplci->appl = appl;
2533                 rplci->cr_enquiry=TRUE;
2534                 add_p(rplci,CAI,"\x01\x80");
2535                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2536                 sig_req(rplci,ASSIGN,DSIG_ID);
2537                 send_req(rplci);
2538               }
2539               else
2540               {
2541                 Info = _OUT_OF_PLCI;
2542                 break;
2543               }
2544             }
2545             else
2546             {
2547               rplci = plci;
2548               rplci->cr_enquiry=FALSE;
2549             }
2550
2551             rplci->command = 0;
2552             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2553             rplci->appl = appl;
2554             rplci->number = Number;
2555
2556             cai[0] = 5;
2557             cai[1] = DEACTIVATION_MWI; /* Function */
2558             WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2559             WRITE_WORD(&cai[4],READ_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2560             add_p(rplci,CAI,cai);
2561             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2562             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2563             sig_req(rplci,S_SERVICE,0);
2564             send_req(rplci);
2565             return FALSE;
2566
2567           default:
2568             Info = 0x300E;  /* not supported */
2569             break;
2570         }
2571         break; /* case SELECTOR_SU_SERV: end */
2572
2573
2574       case SELECTOR_DTMF:
2575         return (dtmf_request (Id, Number, a, plci, appl, msg));
2576
2577
2578
2579       case SELECTOR_LINE_INTERCONNECT:
2580         return (mixer_request (Id, Number, a, plci, appl, msg));
2581
2582
2583
2584       case PRIV_SELECTOR_ECHO_CANCELLER:
2585         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2586         return (ec_request (Id, Number, a, plci, appl, msg));
2587
2588       case SELECTOR_ECHO_CANCELLER:
2589         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2590         return (ec_request (Id, Number, a, plci, appl, msg));
2591
2592
2593       case SELECTOR_V42BIS:
2594       default:
2595         Info = _FACILITY_NOT_SUPPORTED;
2596         break;
2597     } /* end of switch(selector) */
2598   }
2599
2600   dbug(1,dprintf("SendFacRc"));
2601   sendf(appl,
2602         _FACILITY_R|CONFIRM,
2603         Id,
2604         Number,
2605         "wws",Info,selector,SSparms);
2606   return FALSE;
2607 }
2608
2609 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
2610 {
2611   dbug(1,dprintf("facility_res"));
2612   return FALSE;
2613 }
2614
2615 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2616 {
2617   word Info = 0;
2618   byte req;
2619   byte len;
2620   word w;
2621   word fax_control_bits, fax_feature_bits, fax_info_change;
2622   API_PARSE * ncpi;
2623     byte pvc[2];
2624
2625     API_PARSE fax_parms[9];
2626   word i;
2627
2628
2629   dbug(1,dprintf("connect_b3_req"));
2630   if(plci)
2631   {
2632     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2633      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2634     {
2635       Info = _WRONG_STATE;
2636     }
2637     else
2638     {
2639       /* local reply if assign unsuccessfull
2640          or B3 protocol allows only one layer 3 connection
2641            and already connected
2642              or B2 protocol not any LAPD
2643                and connect_b3_req contradicts originate/answer direction */
2644       if (!plci->NL.Id
2645        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2646         && ((plci->channels != 0)
2647          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2648           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2649       {
2650         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2651                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2652         Info = _WRONG_STATE;
2653         sendf(appl,                                                        
2654               _CONNECT_B3_R|CONFIRM,
2655               Id,
2656               Number,
2657               "w",Info);
2658         return FALSE;
2659       }
2660       plci->requested_options_conn = 0;
2661
2662       req = N_CONNECT;
2663       ncpi = &parms[0];
2664       if(plci->B3_prot==2 || plci->B3_prot==3)
2665       {
2666         if(ncpi->length>2)
2667         {
2668           /* check for PVC */
2669           if(ncpi->info[2] || ncpi->info[3])
2670           {
2671             pvc[0] = ncpi->info[3];
2672             pvc[1] = ncpi->info[2];
2673             add_d(plci,2,pvc);
2674             req = N_RESET;
2675           }
2676           else
2677           {
2678             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2679             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2680           }
2681         }
2682       }
2683       else if(plci->B3_prot==5)
2684       {
2685         if (plci->NL.Id && !plci->nl_remove_id)
2686         {
2687           fax_control_bits = READ_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2688           fax_feature_bits = READ_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2689           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2690            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2691           {
2692             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2693             fax_info_change = FALSE;
2694             if (ncpi->length >= 4)
2695             {
2696               w = READ_WORD(&ncpi->info[3]);
2697               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2698               {
2699                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2700                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2701                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2702                 fax_info_change = TRUE;
2703               }
2704               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2705               if (w & 0x0002)  /* Fax-polling request */
2706                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2707               if ((w & 0x0004) /* Request to send / poll another document */
2708                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2709               {
2710                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2711               }
2712               if (ncpi->length >= 6)
2713               {
2714                 w = READ_WORD(&ncpi->info[5]);
2715                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2716                 {
2717                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2718                   fax_info_change = TRUE;
2719                 }
2720
2721                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2722                  && (READ_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2723                 {
2724                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2725                 }
2726                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2727                  && (READ_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2728                 {
2729                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2730                 }
2731                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2732                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2733                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2735                 {
2736                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2737                     Info = _WRONG_MESSAGE_FORMAT;
2738                   else
2739                   {
2740                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2741                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2742       {
2743                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2744                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2745                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2746       }
2747                     w = fax_parms[4].length;
2748                     if (w > 20)
2749                       w = 20;
2750                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2751                     for (i = 0; i < w; i++)
2752                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2753                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2754                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2755                     w = fax_parms[5].length;
2756                     if (w > 20)
2757                       w = 20;
2758                     plci->fax_connect_info_buffer[len++] = (byte) w;
2759                     for (i = 0; i < w; i++)
2760                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2761                     w = fax_parms[6].length;
2762                     if (w > 20)
2763                       w = 20;
2764                     plci->fax_connect_info_buffer[len++] = (byte) w;
2765                     for (i = 0; i < w; i++)
2766                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2767                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2768                       & (1L << PRIVATE_FAX_NONSTANDARD))
2769       {
2770                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2771         {
2772                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2773                         plci->fax_connect_info_buffer[len++] = 0;
2774         }
2775                       else
2776                       {
2777           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2778             plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]);
2779    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2780           for (i = 0; i < fax_parms[7].length; i++)
2781      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2782                       }
2783                     }
2784                   }
2785                 }
2786                 else
2787                 {
2788                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2789                 }
2790                 fax_info_change = TRUE;
2791
2792               }
2793               if (fax_control_bits != READ_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2794               {
2795                 WRITE_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2796                 fax_info_change = TRUE;
2797               }
2798             }
2799             if (Info == GOOD)
2800             {
2801               plci->fax_connect_info_length = len;
2802               if (fax_info_change)
2803               {
2804                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2805                 {
2806                   start_internal_command (Id, plci, fax_connect_info_command);
2807                   return FALSE;
2808                 }
2809                 else
2810                 {
2811                   start_internal_command (Id, plci, fax_adjust_b23_command);
2812                   return FALSE;
2813                 }
2814               }
2815             }
2816           }
2817           else  Info = _WRONG_STATE;
2818         }
2819         else  Info = _WRONG_STATE;
2820       }
2821
2822       else if (plci->B3_prot == B3_RTP)
2823       {
2824         plci->internal_req_buffer[0] = ncpi->length + 1;
2825         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2826         for (w = 0; w < ncpi->length; w++)
2827           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2828         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2829         return FALSE;
2830       }
2831
2832       if(!Info)
2833       {
2834         nl_req_ncci(plci,req,0);
2835         return 1;
2836       }
2837     }
2838   }
2839   else Info = _WRONG_IDENTIFIER;
2840
2841   sendf(appl,
2842         _CONNECT_B3_R|CONFIRM,
2843         Id,
2844         Number,
2845         "w",Info);
2846   return FALSE;
2847 }
2848
2849 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2850 {
2851   word ncci;
2852   API_PARSE * ncpi;
2853   byte req;
2854
2855   word w;
2856
2857
2858     API_PARSE fax_parms[9];
2859   word i;
2860   byte len;
2861
2862
2863   dbug(1,dprintf("connect_b3_res"));
2864
2865   ncci = (word)(Id>>16);
2866   if(plci && ncci) {
2867     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2868       if (READ_WORD (&parms[0].info[0]) != 0)
2869       {
2870         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2871         channel_request_xon (plci, a->ncci_ch[ncci]);
2872         channel_xmit_xon (plci);
2873         cleanup_ncci_data (plci, ncci);
2874         nl_req_ncci(plci,N_DISC,(byte)ncci);
2875         return 1;
2876       }
2877       a->ncci_state[ncci] = INC_ACT_PENDING;
2878
2879       req = N_CONNECT_ACK;
2880       ncpi = &parms[1];
2881       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2882       {
2883
2884         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2885           & (1L << PRIVATE_FAX_NONSTANDARD))
2886  {
2887    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2888     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2889     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2890    {
2891             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2892             if (plci->fax_connect_info_length < len)
2893             {
2894               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2895               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2896             }
2897             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2898             {
2899               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2900             }
2901             else
2902             {
2903               if (plci->fax_connect_info_length <= len)
2904                 plci->fax_connect_info_buffer[len] = 0;
2905               len += 1 + plci->fax_connect_info_buffer[len];
2906               if (plci->fax_connect_info_length <= len)
2907                 plci->fax_connect_info_buffer[len] = 0;
2908               len += 1 + plci->fax_connect_info_buffer[len];
2909               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2910                 plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]);
2911               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2912               for (i = 0; i < fax_parms[7].length; i++)
2913                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2914             }
2915             plci->fax_connect_info_length = len;
2916             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2917             start_internal_command (Id, plci, fax_connect_ack_command);
2918      return FALSE;
2919           }
2920         }
2921
2922         nl_req_ncci(plci,req,(byte)ncci);
2923         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2924          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2925         {
2926           if (plci->B3_prot == 4)
2927             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2928           else
2929             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2930           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2931         }
2932       }
2933
2934       else if (plci->B3_prot == B3_RTP)
2935       {
2936         plci->internal_req_buffer[0] = ncpi->length + 1;
2937         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2938         for (w = 0; w < ncpi->length; w++)
2939           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2940         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2941         return FALSE;
2942       }
2943
2944       else
2945       {
2946         if(ncpi->length>2) {
2947           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2948           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2949         }
2950         nl_req_ncci(plci,req,(byte)ncci);
2951         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2952         if (plci->adjust_b_restore)
2953         {
2954           plci->adjust_b_restore = FALSE;
2955           start_internal_command (Id, plci, adjust_b_restore);
2956         }
2957       }
2958       return 1;
2959     }
2960   }
2961   return FALSE;
2962 }
2963
2964 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2965 {
2966   word ncci;
2967
2968   ncci = (word)(Id>>16);
2969   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2970
2971   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2972    && (plci->State != OUTG_DIS_PENDING))
2973   {
2974     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2975       a->ncci_state[ncci] = CONNECTED;
2976       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2977       channel_request_xon (plci, a->ncci_ch[ncci]);
2978       channel_xmit_xon (plci);
2979     }
2980   }
2981   return FALSE;
2982 }
2983
2984 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2985 {
2986   word Info;
2987   word ncci;
2988   API_PARSE * ncpi;
2989
2990   dbug(1,dprintf("disconnect_b3_req"));
2991
2992   Info = _WRONG_IDENTIFIER;
2993   ncci = (word)(Id>>16);
2994   if (plci && ncci)
2995   {
2996     Info = _WRONG_STATE;
2997     if ((a->ncci_state[ncci] == CONNECTED)
2998      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2999      || (a->ncci_state[ncci] == INC_CON_PENDING)
3000      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3001     {
3002       a->ncci_state[ncci] = OUTG_DIS_PENDING;
3003       channel_request_xon (plci, a->ncci_ch[ncci]);
3004       channel_xmit_xon (plci);
3005
3006       if (a->ncci[ncci].data_pending
3007        && ((plci->B3_prot == B3_TRANSPARENT)
3008         || (plci->B3_prot == B3_T30)
3009         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3010       {
3011         plci->send_disc = (byte)ncci;
3012         plci->command = 0;
3013         return FALSE;
3014       }
3015       else
3016       {
3017         cleanup_ncci_data (plci, ncci);
3018
3019         if(plci->B3_prot==2 || plci->B3_prot==3)
3020         {
3021           ncpi = &parms[0];
3022           if(ncpi->length>3)
3023           {
3024             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3025           }
3026         }
3027         nl_req_ncci(plci,N_DISC,(byte)ncci);
3028       }
3029       return 1;
3030     }
3031   }
3032   sendf(appl,
3033         _DISCONNECT_B3_R|CONFIRM,
3034         Id,
3035         Number,
3036         "w",Info);
3037   return FALSE;
3038 }
3039
3040 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3041 {
3042   word ncci;
3043   word i;
3044
3045   ncci = (word)(Id>>16);
3046   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3047   if(plci && ncci) {
3048     plci->requested_options_conn = 0;
3049     plci->fax_connect_info_length = 0;
3050     plci->ncpi_state = 0x00;
3051     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3052       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3053     {
3054       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3055     }
3056     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3057     if(i<MAX_CHANNELS_PER_PLCI) {
3058       if(plci->channels)plci->channels--;
3059       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3060       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3061
3062       ncci_free_receive_buffers (plci, ncci);
3063
3064       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3065         if(plci->State == SUSPENDING){
3066           sendf(plci->appl,
3067                 _FACILITY_I,
3068                 Id & 0xffffL,
3069                 0,
3070                 "ws", (word)3, "\x03\x04\x00\x00");
3071           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3072         }
3073         plci_remove(plci);
3074         plci->State=IDLE;
3075       }
3076     }
3077     else
3078     {
3079       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3080        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3081        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3082       {
3083         ncci_free_receive_buffers (plci, ncci);
3084
3085         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3086
3087         plci->adapter->ncci_state[ncci] = IDLE;
3088         start_internal_command (Id, plci, fax_disconnect_command);
3089         return 1;
3090       }
3091     }
3092   }
3093   return FALSE;
3094 }
3095
3096 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3097 {
3098   NCCI   *ncci_ptr;
3099   DATA_B3_DESC   *data;
3100   word Info;
3101   word ncci;
3102   word i;
3103
3104   dbug(1,dprintf("data_b3_req"));
3105
3106   Info = _WRONG_IDENTIFIER;
3107   ncci = (word)(Id>>16);
3108   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3109
3110   if (plci && ncci)
3111   {
3112     Info = _WRONG_STATE;
3113     if ((a->ncci_state[ncci] == CONNECTED)
3114      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3115     {
3116         /* queue data */
3117       ncci_ptr = &(a->ncci[ncci]);
3118       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3119       if (i >= MAX_DATA_B3)
3120         i -= MAX_DATA_B3;
3121       data = &(ncci_ptr->DBuffer[i]);
3122       data->Number = Number;
3123       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3124        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3125       {
3126
3127         data->P = (byte   *)(*((dword   *)(parms[0].info)));
3128
3129       }
3130       else
3131         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3132       data->Length = READ_WORD(parms[1].info);
3133       data->Handle = READ_WORD(parms[2].info);
3134       data->Flags = READ_WORD(parms[3].info);
3135       (ncci_ptr->data_pending)++;
3136
3137         /* check for delivery confirmation */
3138       if (data->Flags & 0x0004)
3139       {
3140         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3141         if (i >= MAX_DATA_ACK)
3142           i -= MAX_DATA_ACK;
3143         ncci_ptr->DataAck[i].Number = data->Number;
3144         ncci_ptr->DataAck[i].Handle = data->Handle;
3145         (ncci_ptr->data_ack_pending)++;
3146       }
3147
3148       send_data(plci);
3149       return FALSE;
3150     }
3151   }
3152   if (appl)
3153   {
3154     if (plci)
3155     {
3156       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3157        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3158       {
3159
3160         TransmitBufferFree (appl, (byte   *)(*((dword   *)(parms[0].info))));
3161
3162       }
3163     }
3164     sendf(appl,
3165           _DATA_B3_R|CONFIRM,
3166           Id,
3167           Number,
3168           "ww",READ_WORD(parms[2].info),Info);
3169   }
3170   return FALSE;
3171 }
3172
3173 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3174 {
3175   word n;
3176   word ncci;
3177   word NCCIcode;
3178
3179   dbug(1,dprintf("data_b3_res"));
3180
3181   ncci = (word)(Id>>16);
3182   if(plci && ncci) {
3183     n = READ_WORD(parms[0].info);
3184     dbug(1,dprintf("free(%d)",n));
3185     NCCIcode = ncci | (((word) a->Id) << 8);
3186     if(n<appl->MaxBuffer &&
3187        appl->DataNCCI[n]==NCCIcode &&
3188        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3189       dbug(1,dprintf("found"));
3190       appl->DataNCCI[n] = 0;
3191
3192       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3193         channel_request_xon (plci, a->ncci_ch[ncci]);
3194       }
3195       channel_xmit_xon (plci);
3196
3197       if(appl->DataFlags[n] &4) {
3198         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3199         return 1;
3200       }
3201     }
3202   }
3203   return FALSE;
3204 }
3205
3206 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3207 {
3208   word Info;
3209   word ncci;
3210
3211   dbug(1,dprintf("reset_b3_req"));
3212
3213   Info = _WRONG_IDENTIFIER;
3214   ncci = (word)(Id>>16);
3215   if(plci && ncci)
3216   {
3217     Info = _WRONG_STATE;
3218     switch (plci->B3_prot)
3219     {
3220     case B3_ISO8208:
3221     case B3_X25_DCE:
3222       if(a->ncci_state[ncci]==CONNECTED)
3223       {
3224         nl_req_ncci(plci,N_RESET,(byte)ncci);
3225         send_req(plci);
3226         Info = GOOD;
3227       }
3228       break;
3229     case B3_TRANSPARENT:
3230       if(a->ncci_state[ncci]==CONNECTED)
3231       {
3232         start_internal_command (Id, plci, reset_b3_command);
3233         Info = GOOD;
3234       }
3235       break;
3236     }
3237   }
3238   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3239   sendf(appl,
3240         _RESET_B3_R|CONFIRM,
3241         Id,
3242         Number,
3243         "w",Info);
3244   return FALSE;
3245 }
3246
3247 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3248 {
3249   word ncci;
3250
3251   dbug(1,dprintf("reset_b3_res"));
3252
3253   ncci = (word)(Id>>16);
3254   if(plci && ncci) {
3255     switch (plci->B3_prot)
3256     {
3257     case B3_ISO8208:
3258     case B3_X25_DCE:
3259       if(a->ncci_state[ncci]==INC_RES_PENDING)
3260       {
3261         a->ncci_state[ncci] = CONNECTED;
3262         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3263         return TRUE;
3264       }
3265     break;
3266     }
3267   }
3268   return FALSE;
3269 }
3270
3271 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3272 {
3273   word ncci;
3274   API_PARSE * ncpi;
3275   byte req;
3276
3277   dbug(1,dprintf("connect_b3_t90_a_res"));
3278
3279   ncci = (word)(Id>>16);
3280   if(plci && ncci) {
3281     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3282       a->ncci_state[ncci] = CONNECTED;
3283     }
3284     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3285       a->ncci_state[ncci] = CONNECTED;
3286
3287       req = N_CONNECT_ACK;
3288
3289         /* parms[0]==0 for CAPI original message definition! */
3290       if(parms[0].info) {
3291         ncpi = &parms[1];
3292         if(ncpi->length>2) {
3293           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3294           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3295         }
3296       }
3297       nl_req_ncci(plci,req,(byte)ncci);
3298       return 1;
3299     }
3300   }
3301   return FALSE;
3302 }
3303
3304
3305 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3306 {
3307   word Info=0;
3308   word i;
3309   byte tel;
3310     API_PARSE bp_parms[7];
3311
3312   if(!plci || !msg)
3313   {
3314     Info = _WRONG_IDENTIFIER;
3315   }
3316   else
3317   {
3318     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3319                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3320     dbug(1,dprintf("PlciState=0x%x",plci->State));
3321     for(i=0;i<7;i++) bp_parms[i].length = 0;
3322
3323     /* check if no channel is open, no B3 connected only */
3324     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3325      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3326     {
3327       Info = _WRONG_STATE;
3328     }
3329     /* check message format and fill bp_parms pointer */
3330     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3331     {
3332       Info = _WRONG_MESSAGE_FORMAT;
3333     }
3334     else
3335     {
3336       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3337       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3338         if(Id & EXT_CONTROLLER)
3339         {
3340           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3341           return 0;
3342         }
3343         plci->State=INC_CON_CONNECTED_ALERT;
3344         plci->appl = appl;
3345         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3346         dump_c_ind_mask (plci);
3347         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3348         {                         /* its quasi a connect        */
3349           if(test_c_ind_mask_bit (plci, i))
3350             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3351         }
3352       }
3353
3354       api_save_msg(msg, "s", &plci->saved_msg);
3355       tel = plci->tel;
3356       if(Id & EXT_CONTROLLER)
3357       {
3358         if(tel) /* external controller in use by this PLCI */
3359         {
3360           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3361           {
3362             dbug(1,dprintf("Ext_Ctrl in use 1"));
3363             Info = _WRONG_STATE;
3364           }
3365         }
3366         else  /* external controller NOT in use by this PLCI ? */
3367         {
3368           if(a->AdvSignalPLCI)
3369           {
3370             dbug(1,dprintf("Ext_Ctrl in use 2"));
3371             Info = _WRONG_STATE;
3372           }
3373           else /* activate the codec */
3374           {
3375             dbug(1,dprintf("Ext_Ctrl start"));
3376             if(AdvCodecSupport(a, plci, appl, 0) )
3377             {
3378               dbug(1,dprintf("Error in codec procedures"));
3379               Info = _WRONG_STATE;
3380             }
3381             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3382             {
3383               plci->spoofed_msg = AWAITING_SELECT_B;
3384               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3385               plci->command = 0;
3386               dbug(1,dprintf("continue if codec loaded"));
3387               return FALSE;
3388             }
3389           }
3390         }
3391       }
3392       else /* external controller bit is OFF */
3393       {
3394         if(tel) /* external controller in use, need to switch off */
3395         {
3396           if(a->AdvSignalAppl==appl)
3397           {
3398             CodecIdCheck(a, plci);
3399             plci->tel = 0;
3400             plci->adv_nl = 0;
3401             dbug(1,dprintf("Ext_Ctrl disable"));
3402           }
3403           else
3404           {
3405             dbug(1,dprintf("Ext_Ctrl not requested"));
3406           }
3407         }
3408       }
3409       if (!Info)
3410       {
3411         if (plci->call_dir & CALL_DIR_OUT)
3412           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3413         else if (plci->call_dir & CALL_DIR_IN)
3414           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3415         start_internal_command (Id, plci, select_b_command);
3416         return FALSE;
3417       }
3418     }
3419   }
3420   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3421   return FALSE;
3422 }
3423
3424 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3425 {
3426   word command;
3427   word i;
3428   word ncci;
3429   API_PARSE * m;
3430     API_PARSE m_parms[5];
3431   word codec;
3432   byte req;
3433   byte ch;
3434   byte dir;
3435   static byte chi[2] = {0x01,0x00};
3436   static byte lli[2] = {0x01,0x00};
3437   static byte codec_cai[2] = {0x01,0x01};
3438   static byte null_msg = {0};
3439   static API_PARSE null_parms = { 0, &null_msg };
3440   PLCI   * v_plci;
3441   word Info=0;
3442
3443   dbug(1,dprintf("manufacturer_req"));
3444   for(i=0;i<5;i++) m_parms[i].length = 0;
3445
3446   if(READ_DWORD(parms[0].info)!=_DI_MANU_ID) {
3447     Info = _WRONG_MESSAGE_FORMAT;
3448   }
3449   command = READ_WORD(parms[1].info);
3450   m = &parms[2];
3451   if (!Info)
3452   {
3453     switch(command) {
3454     case _DI_ASSIGN_PLCI:
3455       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3456         Info = _WRONG_MESSAGE_FORMAT;
3457         break;
3458       }
3459       codec = READ_WORD(m_parms[0].info);
3460       ch = m_parms[1].info[0];
3461       dir = m_parms[2].info[0];
3462       if((i=get_plci(a))) {
3463         plci = &a->plci[i-1];
3464         plci->appl = appl;
3465         plci->command = _MANUFACTURER_R;
3466         plci->m_command = command;
3467         plci->number = Number;
3468         plci->State = LOCAL_CONNECT;
3469         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3470         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3471
3472         if((ch==1 || ch==2) && (dir<=2)) {
3473           chi[1] = (byte)(0x80|ch);
3474           lli[1] = 0;
3475           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3476           switch(codec)
3477           {
3478           case 0:
3479             Info = add_b1(plci,&m_parms[3],0,0);
3480             break;
3481           case 1:
3482             add_p(plci,CAI,codec_cai);
3483             break;
3484           /* manual 'swich on' to the codec support without signalling */
3485           /* first 'assign plci' with this function, then use */
3486           case 2:
3487             if(AdvCodecSupport(a, plci, appl, 0) ) {
3488               Info = _RESOURCE_ERROR;
3489             }
3490             else {
3491               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3492               lli[1] = 0x10; /* local call codec stream */
3493             }
3494             break;
3495           }
3496
3497           plci->State = LOCAL_CONNECT;
3498           plci->manufacturer = TRUE;
3499           plci->command = _MANUFACTURER_R;
3500           plci->m_command = command;
3501           plci->number = Number;
3502
3503           if(!Info)
3504           {
3505             add_p(plci,LLI,lli);
3506             add_p(plci,CHI,chi);
3507             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3508             sig_req(plci,ASSIGN,DSIG_ID);
3509
3510             if(!codec)
3511             {
3512               Info = add_b23(plci,&m_parms[3]);
3513               if(!Info)
3514               {
3515                 nl_req_ncci(plci,ASSIGN,0);
3516                 send_req(plci);
3517               }
3518             }
3519             if(!Info)
3520             {
3521               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3522               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3523               {
3524                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3525                 plci->spoofed_msg = AWAITING_MANUF_CON;
3526                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3527                 plci->command = 0;
3528                 send_req(plci);
3529                 return FALSE;
3530               }
3531               if(dir==1) {
3532                 sig_req(plci,CALL_REQ,0);
3533               }
3534               else if(!dir){
3535                 sig_req(plci,LISTEN_REQ,0);
3536               }
3537               send_req(plci);
3538             }
3539             else
3540             {
3541               sendf(appl,
3542                     _MANUFACTURER_R|CONFIRM,
3543                     Id,
3544                     Number,
3545                     "dww",_DI_MANU_ID,command,Info);
3546               return 2;
3547             }
3548           }
3549         }
3550       }
3551       else  Info = _OUT_OF_PLCI;
3552       break;
3553
3554     case _DI_IDI_CTRL:
3555       if(!plci)
3556       {
3557         Info = _WRONG_IDENTIFIER;
3558         break;
3559       }
3560       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3561         Info = _WRONG_MESSAGE_FORMAT;
3562         break;
3563       }
3564       req = m_parms[0].info[0];
3565       plci->command = _MANUFACTURER_R;
3566       plci->m_command = command;
3567       plci->number = Number;
3568       if(req==CALL_REQ)
3569       {
3570         plci->b_channel = getChannel(&m_parms[1]);
3571         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3572         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3573         {
3574           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3575           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3576           plci->command = 0;
3577           break;
3578         }
3579       }
3580       else if(req==LAW_REQ)
3581       {
3582         plci->cr_enquiry = TRUE;
3583       }
3584       add_ss(plci,FTY,&m_parms[1]);
3585       sig_req(plci,req,0);
3586       send_req(plci);
3587       if(req==HANGUP)
3588       {      
3589         if (plci->NL.Id && !plci->nl_remove_id)
3590         {
3591           if (plci->channels)
3592           {
3593             for (ncci = 1; ncci < MAX_NCCI+1; i++)
3594             {
3595               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3596               {
3597                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3598                 cleanup_ncci_data (plci, ncci);
3599                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3600               }
3601             }
3602           }
3603           mixer_remove (plci);
3604           nl_req_ncci(plci,REMOVE,0);
3605           send_req(plci);
3606         }  
3607       }
3608       break;
3609
3610     case _DI_SIG_CTRL:
3611     /* signalling control for loop activation B-channel */
3612       if(!plci)
3613       {
3614         Info = _WRONG_IDENTIFIER;
3615         break;
3616       }
3617       if(m->length){
3618         plci->command = _MANUFACTURER_R;
3619         plci->number = Number;
3620         add_ss(plci,FTY,m);
3621         sig_req(plci,SIG_CTRL,0);
3622         send_req(plci);
3623       }
3624       else Info = _WRONG_MESSAGE_FORMAT;
3625       break;
3626
3627     case _DI_RXT_CTRL:
3628     /* activation control for receiver/transmitter B-channel */
3629       if(!plci)
3630       {
3631         Info = _WRONG_IDENTIFIER;
3632         break;
3633       }
3634       if(m->length){
3635         plci->command = _MANUFACTURER_R;
3636         plci->number = Number;
3637         add_ss(plci,FTY,m);
3638         sig_req(plci,DSP_CTRL,0);
3639         send_req(plci);
3640       }
3641       else Info = _WRONG_MESSAGE_FORMAT;
3642       break;
3643
3644     case _DI_ADV_CODEC:
3645     case _DI_DSP_CTRL:
3646       /* TEL_CTRL commands to support non standard adjustments: */
3647       /* Ring on/off, Handset micro volume, external micro vol. */
3648       /* handset+external speaker volume, receiver+transm. gain,*/
3649       /* handsfree on (hookinfo off), set mixer command         */
3650
3651       if(command == _DI_ADV_CODEC)
3652       {
3653         if(!a->AdvCodecPLCI) {
3654           Info = _WRONG_STATE;
3655           break;
3656         }
3657         v_plci = a->AdvCodecPLCI;
3658       }
3659       else
3660       {
3661         if (plci
3662          && (m->length >= 3)
3663          && (m->info[1] == 0x1c)
3664          && (m->info[2] >= 1))
3665         {
3666           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3667           {
3668             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3669             {
3670               Info = _WRONG_STATE;
3671               break;
3672             }
3673             a->adv_voice_coef_length = m->info[2] - 1;
3674             if (a->adv_voice_coef_length > m->length - 3)
3675               a->adv_voice_coef_length = (byte)(m->length - 3);
3676             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3677               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3678             for (i = 0; i < a->adv_voice_coef_length; i++)
3679               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3680             if (plci->B1_facilities & B1_FACILITY_VOICE)
3681               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3682             break;
3683           }
3684           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3685           {
3686             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3687             {
3688               Info = _FACILITY_NOT_SUPPORTED;
3689               break;
3690             }
3691
3692             plci->dtmf_parameter_length = m->info[2] - 1;
3693             if (plci->dtmf_parameter_length > m->length - 3)
3694               plci->dtmf_parameter_length = (byte)(m->length - 3);
3695             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3696               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3697             for (i = 0; i < plci->dtmf_parameter_length; i++)
3698               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3699             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3700               dtmf_parameter_write (plci);
3701             break;
3702
3703           }
3704         }
3705         v_plci = plci;
3706       }
3707
3708       if(!v_plci)
3709       {
3710         Info = _WRONG_IDENTIFIER;
3711         break;
3712       }
3713       if(m->length){
3714         add_ss(v_plci,FTY,m);
3715         sig_req(v_plci,TEL_CTRL,0);
3716         send_req(v_plci);
3717       }
3718       else Info = _WRONG_MESSAGE_FORMAT;
3719
3720       break;
3721
3722     case _DI_OPTIONS_REQUEST:
3723       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3724         Info = _WRONG_MESSAGE_FORMAT;
3725         break;
3726       }
3727       if (READ_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3728       {
3729         Info = _FACILITY_NOT_SUPPORTED;
3730         break;
3731       }
3732       a->requested_options_table[appl->Id-1] = READ_DWORD (m_parms[0].info);
3733       break;
3734
3735
3736
3737     default:
3738       Info = _WRONG_MESSAGE_FORMAT;
3739       break;
3740     }
3741   }
3742
3743   sendf(appl,
3744         _MANUFACTURER_R|CONFIRM,
3745         Id,
3746         Number,
3747         "dww",_DI_MANU_ID,command,Info);
3748   return FALSE;
3749 }
3750
3751
3752 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3753 {
3754   word indication;
3755
3756     API_PARSE m_parms[3];
3757   API_PARSE *ncpi;
3758     API_PARSE fax_parms[9];
3759   word i;
3760   byte len;
3761
3762
3763   dbug(1,dprintf("manufacturer_res"));
3764
3765   if ((msg[0].length == 0)
3766    || (msg[1].length == 0)
3767    || (READ_DWORD(msg[0].info)!=_DI_MANU_ID))
3768   {
3769     return FALSE;
3770   }
3771   indication = READ_WORD(msg[1].info);
3772   switch (indication)
3773   {
3774
3775   case _DI_NEGOTIATE_B3:
3776     if(!plci)
3777       break;
3778     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3779      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3780     {
3781       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3782       break;
3783     }
3784     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3785     {
3786       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3787       break;
3788     }
3789     ncpi = &m_parms[1];
3790     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3791     if (plci->fax_connect_info_length < len)
3792     {
3793       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3794       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3795     }
3796     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3797     {
3798       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3799     }
3800     else
3801     {
3802       if (plci->fax_connect_info_length <= len)
3803         plci->fax_connect_info_buffer[len] = 0;
3804       len += 1 + plci->fax_connect_info_buffer[len];
3805       if (plci->fax_connect_info_length <= len)
3806         plci->fax_connect_info_buffer[len] = 0;
3807       len += 1 + plci->fax_connect_info_buffer[len];
3808       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3809         plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]);
3810       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3811       for (i = 0; i < fax_parms[7].length; i++)
3812         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3813     }
3814     plci->fax_connect_info_length = len;
3815     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3816     start_internal_command (Id, plci, fax_edata_ack_command);
3817     break;
3818
3819   }
3820   return FALSE;
3821 }
3822
3823 /*------------------------------------------------------------------*/
3824 /* IDI callback function                                            */
3825 /*------------------------------------------------------------------*/
3826
3827 void   callback(ENTITY   * e)
3828 {
3829   DIVA_CAPI_ADAPTER   * a;
3830   APPL   * appl;
3831   PLCI   * plci;
3832   CAPI_MSG   *m;
3833   word i, j;
3834   byte rc;
3835   byte ch;
3836   byte req;
3837   byte global_req;
3838   int no_cancel_rc;
3839
3840   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3841                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3842
3843   a = &(adapter[(byte)e->user[0]]);
3844   plci = &(a->plci[e->user[1]]);
3845   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3846
3847   /*
3848      If new protocol code and new XDI is used then CAPI should work
3849      fully in accordance with IDI cpec an look on callback field instead
3850      of Rc field for return codes.
3851    */
3852   if (((e->complete == 0xff) && no_cancel_rc) ||
3853       (e->Rc && !no_cancel_rc)) {
3854     rc = e->Rc;
3855     ch = e->RcCh;
3856     req = e->Req;
3857     e->Rc = 0;
3858
3859     if (e->user[0] & 0x8000)
3860     {
3861       /*
3862          If REMOVE request was sent then we have to wait until
3863          return code with Id set to zero arrives.
3864          All other return codes should be ignored.
3865          */
3866       if (req == REMOVE)
3867       {
3868         if (e->Id)
3869         {
3870           dbug(1,dprintf("cancel RC in REMOVE state"));
3871           return;
3872         }
3873         channel_flow_control_remove (plci);
3874         for (i = 0; i < 256; i++)
3875         {
3876           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3877             a->FlowControlIdTable[i] = 0;
3878         }
3879         plci->nl_remove_id = 0;
3880         if (plci->rx_dma_descriptor > 0) {
3881           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3882           plci->rx_dma_descriptor = 0;
3883         }
3884       }
3885       if (rc == OK_FC)
3886       {
3887         a->FlowControlIdTable[ch] = e->Id;
3888         a->FlowControlSkipTable[ch] = 0;
3889
3890         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3891         a->ch_flow_plci[ch] = plci->Id;
3892         plci->nl_req = 0;
3893       }
3894       else
3895       {
3896         /*
3897           Cancel return codes self, if feature was requested
3898           */
3899         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3900           a->FlowControlIdTable[ch] = 0;
3901           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3902             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3903             return;
3904           }
3905         }
3906
3907         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3908         {
3909           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3910           if (ch == e->ReqCh)
3911             plci->nl_req = 0;
3912         }
3913         else
3914           plci->nl_req = 0;
3915       }
3916       if (plci->nl_req)
3917         control_rc (plci, 0, rc, ch, 0, TRUE);
3918       else
3919       {
3920         if (req == N_XON)
3921         {
3922           channel_x_on (plci, ch);
3923           if (plci->internal_command)
3924             control_rc (plci, req, rc, ch, 0, TRUE);
3925         }
3926         else
3927         {
3928           if (plci->nl_global_req)
3929           {
3930             global_req = plci->nl_global_req;
3931             plci->nl_global_req = 0;
3932             if (rc != ASSIGN_OK) {
3933               e->Id = 0;
3934               if (plci->rx_dma_descriptor > 0) {
3935                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3936                 plci->rx_dma_descriptor = 0;
3937               }
3938             }
3939             channel_xmit_xon (plci);
3940             control_rc (plci, 0, rc, ch, global_req, TRUE);
3941           }
3942           else if (plci->data_sent)
3943           {
3944             channel_xmit_xon (plci);
3945             plci->data_sent = FALSE;
3946             plci->NL.XNum = 1;
3947             data_rc (plci, ch);
3948             if (plci->internal_command)
3949               control_rc (plci, req, rc, ch, 0, TRUE);
3950           }
3951           else
3952           {
3953             channel_xmit_xon (plci);
3954             control_rc (plci, req, rc, ch, 0, TRUE);
3955           }
3956         }
3957       }
3958     }
3959     else
3960     {
3961       /*
3962          If REMOVE request was sent then we have to wait until
3963          return code with Id set to zero arrives.
3964          All other return codes should be ignored.
3965          */
3966       if (req == REMOVE)
3967       {
3968         if (e->Id)
3969         {
3970           dbug(1,dprintf("cancel RC in REMOVE state"));
3971           return;
3972         }
3973         plci->sig_remove_id = 0;
3974       }
3975       plci->sig_req = 0;
3976       if (plci->sig_global_req)
3977       {
3978         global_req = plci->sig_global_req;
3979         plci->sig_global_req = 0;
3980         if (rc != ASSIGN_OK)
3981           e->Id = 0;
3982         channel_xmit_xon (plci);
3983         control_rc (plci, 0, rc, ch, global_req, FALSE);
3984       }
3985       else
3986       {
3987         channel_xmit_xon (plci);
3988         control_rc (plci, req, rc, ch, 0, FALSE);
3989       }
3990     }
3991     /*
3992       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3993       same callback. Also if new XDI and protocol code used then jump
3994       direct to finish.
3995       */
3996     if (no_cancel_rc) {
3997       channel_xmit_xon(plci);
3998       goto capi_callback_suffix;
3999     }
4000   }
4001
4002   channel_xmit_xon(plci);
4003
4004   if (e->Ind) {
4005     if (e->user[0] &0x8000) {
4006       byte Ind = e->Ind & 0x0f;
4007       byte Ch = e->IndCh;
4008       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4009           (a->ch_flow_plci[Ch] == plci->Id)) {
4010         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4011           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4012         }
4013         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4014       }
4015       nl_ind(plci);
4016       if ((e->RNR != 1) &&
4017           (a->ch_flow_plci[Ch] == plci->Id) &&
4018           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4019         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4020         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4021       }
4022     } else {
4023       sig_ind(plci);
4024     }
4025     e->Ind = 0;
4026   }
4027
4028 capi_callback_suffix:
4029
4030   while (!plci->req_in
4031    && !plci->internal_command
4032    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4033   {
4034     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4035
4036     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4037
4038     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4039     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4040     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4041       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4042     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4043     {
4044       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4045       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4046     }
4047     else
4048     {
4049       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4050     }
4051     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4052     {
4053       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4054       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4055     }
4056     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4057     {
4058       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4059       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4060     }
4061     i = api_put (appl, m);
4062     if (i != 0)
4063     {
4064       if (m->header.command == _DATA_B3_R)
4065
4066         TransmitBufferFree (appl, (byte   *)(m->info.data_b3_req.Data));
4067
4068       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4069       break;
4070     }
4071
4072     if (plci->li_notify_update)
4073     {
4074       plci->li_notify_update = FALSE;
4075       mixer_notify_update (plci, FALSE);
4076     }
4077
4078   }
4079   send_data(plci);
4080   send_req(plci);
4081 }
4082
4083
4084 void control_rc(PLCI   * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4085 {
4086   dword Id;
4087   dword rId;
4088   word Number;
4089   word Info=0;
4090   word i;
4091   word ncci;
4092   DIVA_CAPI_ADAPTER   * a;
4093   APPL   * appl;
4094   PLCI   * rplci;
4095     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4096     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4097
4098   if (!plci) {
4099     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4100     return;
4101   }
4102   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4103   if(plci->req_in!=plci->req_out)
4104   {
4105     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4106     {
4107       dbug(1,dprintf("req_1return"));
4108       return;
4109     }
4110     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4111   }
4112   plci->req_in = plci->req_in_start = plci->req_out = 0;
4113   dbug(1,dprintf("control_rc"));
4114
4115   appl = plci->appl;
4116   a = plci->adapter;
4117   ncci = a->ch_ncci[ch];
4118   if(appl)
4119   {
4120     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4121     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4122     Number = plci->number;
4123     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));
4124     dbug(1,dprintf("channels=0x%x",plci->channels));
4125     if (plci_remove_check(plci))
4126       return;
4127     if(req==REMOVE && rc==ASSIGN_OK)
4128     {
4129       sig_req(plci,HANGUP,0);
4130       sig_req(plci,REMOVE,0);
4131       send_req(plci);
4132     }
4133     if(plci->command)
4134     {
4135       switch(plci->command)
4136       {
4137       case C_HOLD_REQ:
4138         dbug(1,dprintf("HoldRC=0x%x",rc));
4139         SSparms[1] = (byte)S_HOLD;
4140         if(rc!=OK)
4141         {
4142           plci->SuppState = IDLE;
4143           Info = 0x2001;
4144         }
4145         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4146         break;
4147
4148       case C_RETRIEVE_REQ:
4149         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4150         SSparms[1] = (byte)S_RETRIEVE;
4151         if(rc!=OK)
4152         {
4153           plci->SuppState = CALL_HELD;
4154           Info = 0x2001;
4155         }
4156         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4157         break;
4158
4159       case _INFO_R:
4160         dbug(1,dprintf("InfoRC=0x%x",rc));
4161         if(rc!=OK) Info=_WRONG_STATE;
4162         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4163         break;
4164
4165       case _CONNECT_R:
4166         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4167         if (plci->State == INC_DIS_PENDING)
4168           break;
4169         if(plci->Sig.Id!=0xff)
4170         {
4171           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4172            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4173           {
4174             dbug(1,dprintf("No more IDs/Call_Req failed"));
4175             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4176             plci_remove(plci);
4177             plci->State = IDLE;
4178             break;
4179           }
4180           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4181           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4182         }
4183         else /* D-ch activation */
4184         {
4185           if (rc != ASSIGN_OK)
4186           {
4187             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4188             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4189             plci_remove(plci);
4190             plci->State = IDLE;
4191             break;
4192           }
4193           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4194           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4195           plci->State = INC_ACT_PENDING;
4196         }
4197         break;
4198
4199       case _CONNECT_I|RESPONSE:
4200         if (plci->State != INC_DIS_PENDING)
4201           plci->State = INC_CON_ACCEPT;
4202         break;
4203
4204       case _DISCONNECT_R:
4205         if (plci->State == INC_DIS_PENDING)
4206           break;
4207         if(plci->Sig.Id!=0xff)
4208         {
4209           plci->State = OUTG_DIS_PENDING;
4210           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4211         }
4212         break;
4213
4214       case SUSPEND_REQ:
4215         break;
4216
4217       case RESUME_REQ:
4218         break;
4219
4220       case _CONNECT_B3_R:
4221         if(rc!=OK)
4222         {
4223           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4224           break;
4225         }
4226         ncci = get_ncci (plci, ch, 0);
4227         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4228         plci->channels++;
4229         if(req==N_RESET)
4230         {
4231           a->ncci_state[ncci] = INC_ACT_PENDING;
4232           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4233           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4234         }
4235         else
4236         {
4237           a->ncci_state[ncci] = OUTG_CON_PENDING;
4238           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4239         }
4240         break;
4241
4242       case _CONNECT_B3_I|RESPONSE:
4243         break;
4244
4245       case _RESET_B3_R:
4246 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4247         break;
4248
4249       case _DISCONNECT_B3_R:
4250         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4251         break;
4252
4253       case _MANUFACTURER_R:
4254         break;
4255
4256       case PERM_LIST_REQ:
4257         if(rc!=OK)
4258         {
4259           Info = _WRONG_IDENTIFIER;
4260           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4261           plci_remove(plci);
4262         }
4263         else
4264           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4265         break;
4266
4267       default:
4268         break;
4269       }
4270       plci->command = 0;
4271     }
4272     else if (plci->internal_command)
4273     {
4274       switch(plci->internal_command)
4275       {
4276       case BLOCK_PLCI:
4277         return;
4278
4279       case GET_MWI_STATE:
4280         if(rc==OK) /* command supported, wait for indication */
4281         {
4282           return;
4283         }
4284         plci_remove(plci);
4285         break;
4286
4287         /* Get Supported Services */
4288       case GETSERV_REQ_PEND:
4289         if(rc==OK) /* command supported, wait for indication */
4290         {
4291           break;
4292         }
4293         WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4294         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4295         plci_remove(plci);
4296         break;
4297
4298       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4299       case INTERR_NUMBERS_REQ_PEND:
4300       case CF_START_PEND:                  /* Call Forwarding Start pending */
4301       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4302       case CCBS_REQUEST_REQ_PEND:
4303       case CCBS_DEACTIVATE_REQ_PEND:
4304       case CCBS_INTERROGATE_REQ_PEND:
4305         switch(plci->internal_command)
4306         {
4307           case INTERR_DIVERSION_REQ_PEND:
4308             SSparms[1] = S_INTERROGATE_DIVERSION;
4309             break;
4310           case INTERR_NUMBERS_REQ_PEND:
4311             SSparms[1] = S_INTERROGATE_NUMBERS;
4312             break;
4313           case CF_START_PEND:
4314             SSparms[1] = S_CALL_FORWARDING_START;
4315             break;
4316           case CF_STOP_PEND:
4317             SSparms[1] = S_CALL_FORWARDING_STOP;
4318             break;
4319           case CCBS_REQUEST_REQ_PEND:
4320             SSparms[1] = S_CCBS_REQUEST;
4321             break;
4322           case CCBS_DEACTIVATE_REQ_PEND:
4323             SSparms[1] = S_CCBS_DEACTIVATE;
4324             break;
4325           case CCBS_INTERROGATE_REQ_PEND:
4326             SSparms[1] = S_CCBS_INTERROGATE;
4327             break;
4328         }
4329         if(global_req==ASSIGN)
4330         {
4331           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4332           return;
4333         }
4334         if(!plci->appl) break;
4335         if(rc==ISDN_GUARD_REJ)
4336         {
4337           Info = _CAPI_GUARD_ERROR;
4338         }
4339         else if(rc!=OK)
4340         {
4341           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4342         }
4343         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4344               plci->number,"wws",Info,(word)3,SSparms);
4345         if(Info) plci_remove(plci);
4346         break;
4347
4348         /* 3pty conference pending */
4349       case PTY_REQ_PEND:
4350         if(!plci->relatedPTYPLCI) break;
4351         rplci = plci->relatedPTYPLCI;
4352         SSparms[1] = plci->ptyState;
4353         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4354         if(rplci->tel) rId|=EXT_CONTROLLER;
4355         if(rc!=OK)
4356         {
4357           Info = 0x300E; /* not supported */
4358           plci->relatedPTYPLCI = 0;
4359           plci->ptyState = 0;
4360         }
4361         sendf(rplci->appl,
4362               _FACILITY_R|CONFIRM,
4363               rId,
4364               plci->number,
4365               "wws",Info,(word)3,SSparms);
4366         break;
4367
4368         /* Explicit Call Transfer pending */
4369       case ECT_REQ_PEND:
4370         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4371         if(!plci->relatedPTYPLCI) break;
4372         rplci = plci->relatedPTYPLCI;
4373         SSparms[1] = S_ECT;
4374         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4375         if(rplci->tel) rId|=EXT_CONTROLLER;
4376         if(rc!=OK)
4377         {
4378           Info = 0x300E; /* not supported */
4379           plci->relatedPTYPLCI = 0;
4380           plci->ptyState = 0;
4381         }
4382         sendf(rplci->appl,
4383               _FACILITY_R|CONFIRM,
4384               rId,
4385               plci->number,
4386               "wws",Info,(word)3,SSparms);
4387         break;
4388
4389       case _MANUFACTURER_R:
4390         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4391         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4392         {
4393           dbug(1,dprintf("No more IDs"));
4394           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4395           plci_remove(plci);  /* after codec init, internal codec commands pending */
4396         }
4397         break;
4398
4399       case _CONNECT_R:
4400         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4401         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4402         {
4403           dbug(1,dprintf("No more IDs"));
4404           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4405           plci_remove(plci);  /* after codec init, internal codec commands pending */
4406         }
4407         break;
4408
4409       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4410         return;
4411
4412       case PERM_COD_CALL:
4413         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4414         plci->internal_command = PERM_COD_CONN_PEND;
4415         return;
4416
4417       case PERM_COD_ASSIGN:
4418         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4419         if(rc!=ASSIGN_OK) break;
4420         sig_req(plci,CALL_REQ,0);
4421         send_req(plci);
4422         plci->internal_command = PERM_COD_CALL;
4423         return;
4424
4425         /* Null Call Reference Request pending */
4426       case C_NCR_FAC_REQ:
4427         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4428         if(global_req==ASSIGN)
4429         {
4430           if(rc==ASSIGN_OK)
4431           {
4432             return;
4433           }
4434           else
4435           {
4436             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4437             appl->NullCREnable = FALSE;
4438             plci_remove(plci);
4439           }
4440         }
4441         else if(req==NCR_FACILITY)
4442         {
4443           if(rc==OK)
4444           {
4445             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4446           }
4447           else
4448           {
4449             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4450             appl->NullCREnable = FALSE;
4451           }
4452           plci_remove(plci);
4453         }
4454         break;
4455
4456       case HOOK_ON_REQ:
4457         if(plci->channels)
4458         {
4459           if(a->ncci_state[ncci]==CONNECTED)
4460           {
4461             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4462             cleanup_ncci_data (plci, ncci);
4463             nl_req_ncci(plci,N_DISC,(byte)ncci);
4464           }
4465           break;
4466         }
4467         break;
4468
4469       case HOOK_OFF_REQ:
4470         if (plci->State == INC_DIS_PENDING)
4471           break;
4472         sig_req(plci,CALL_REQ,0);
4473         send_req(plci);
4474         plci->State=OUTG_CON_PENDING;
4475         break;
4476
4477
4478       case MWI_ACTIVATE_REQ_PEND:
4479       case MWI_DEACTIVATE_REQ_PEND:
4480         if(global_req == ASSIGN && rc==ASSIGN_OK)
4481         {
4482           dbug(1,dprintf("MWI_REQ assigned"));
4483           return;
4484         }
4485         else if(rc!=OK)
4486         {                 
4487           if(rc==WRONG_IE)
4488           {
4489             Info = 0x2007; /* Illegal message parameter coding */
4490             dbug(1,dprintf("MWI_REQ illegal parameter"));
4491           }
4492           else
4493           {
4494             Info = 0x300B; /* not supported */                      
4495             dbug(1,dprintf("MWI_REQ not supported"));
4496           }
4497           /* 0x3010: Request not allowed in this state */
4498           WRITE_WORD(&SSparms[4],0x300E); /* SS not supported */
4499                     
4500         }
4501         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4502         {
4503           WRITE_WORD(&SSparms[1],S_MWI_ACTIVATE);
4504         }
4505         else WRITE_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4506
4507         if(plci->cr_enquiry)
4508         {
4509           sendf(plci->appl,
4510                 _FACILITY_R|CONFIRM,
4511                 Id&0xf,
4512                 plci->number,
4513                 "wws",Info,(word)3,SSparms);
4514           if(rc!=OK) plci_remove(plci);
4515         }
4516         else
4517         {
4518           sendf(plci->appl,
4519                 _FACILITY_R|CONFIRM,
4520                 Id,
4521                 plci->number,
4522                 "wws",Info,(word)3,SSparms);
4523         }
4524         break;
4525
4526       case CONF_BEGIN_REQ_PEND:
4527       case CONF_ADD_REQ_PEND:
4528       case CONF_SPLIT_REQ_PEND:
4529       case CONF_DROP_REQ_PEND:
4530       case CONF_ISOLATE_REQ_PEND:
4531       case CONF_REATTACH_REQ_PEND:
4532         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4533         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4534         rplci = plci;
4535         rId = Id;
4536         switch(plci->internal_command)
4537         {
4538           case CONF_BEGIN_REQ_PEND:
4539             SSparms[1] = S_CONF_BEGIN;
4540             break;
4541           case CONF_ADD_REQ_PEND:
4542             SSparms[1] = S_CONF_ADD;
4543             rplci = plci->relatedPTYPLCI;
4544             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4545             break;
4546           case CONF_SPLIT_REQ_PEND:
4547             SSparms[1] = S_CONF_SPLIT;
4548             break;
4549           case CONF_DROP_REQ_PEND:
4550             SSparms[1] = S_CONF_DROP;
4551             break;
4552           case CONF_ISOLATE_REQ_PEND:
4553             SSparms[1] = S_CONF_ISOLATE;
4554             break;
4555           case CONF_REATTACH_REQ_PEND:
4556             SSparms[1] = S_CONF_REATTACH;
4557             break;
4558         }
4559         
4560         if(rc!=OK)
4561         {
4562           Info = 0x300E; /* not supported */
4563           plci->relatedPTYPLCI = 0;
4564           plci->ptyState = 0;
4565         }
4566         sendf(rplci->appl,
4567               _FACILITY_R|CONFIRM,
4568               rId,
4569               plci->number,
4570               "wws",Info,(word)3,SSparms);
4571         break;
4572
4573       case VSWITCH_REQ_PEND:
4574         if(rc!=OK)
4575         {
4576           if(plci->relatedPTYPLCI)
4577           {
4578             plci->relatedPTYPLCI->vswitchstate=0;
4579             plci->relatedPTYPLCI->vsprot=0;
4580             plci->relatedPTYPLCI->vsprotdialect=0;    
4581           }
4582           plci->vswitchstate=0;
4583           plci->vsprot=0;
4584           plci->vsprotdialect=0;
4585         }
4586         else
4587         {
4588           if(plci->relatedPTYPLCI &&
4589              plci->vswitchstate==1 &&
4590              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4591             plci->vswitchstate=3;
4592         }
4593         break;
4594
4595   /* Call Deflection Request pending (SSCT) */
4596       case CD_REQ_PEND:
4597         SSparms[1] = S_CALL_DEFLECTION;
4598         if(rc!=OK)
4599         {
4600           Info = 0x300E; /* not supported */
4601           plci->appl->CDEnable = 0;
4602         }  
4603         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4604           plci->number,"wws",Info,(word)3,SSparms);
4605         break;
4606
4607       case RTP_CONNECT_B3_REQ_COMMAND_2:
4608         if (rc == OK)
4609         {
4610           ncci = get_ncci (plci, ch, 0);
4611           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4612           plci->channels++;
4613           a->ncci_state[ncci] = OUTG_CON_PENDING;
4614         }
4615
4616       default:
4617         if (plci->internal_command_queue[0])
4618         {
4619           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4620           if (plci->internal_command)
4621             return;
4622         }
4623         break;
4624       }
4625       next_internal_command (Id, plci);
4626     }
4627   }
4628   else /* appl==0 */
4629   {
4630     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4631     if(plci->tel) Id|=EXT_CONTROLLER;
4632
4633     switch(plci->internal_command)
4634     {
4635     case BLOCK_PLCI:
4636       return;
4637
4638     case START_L1_SIG_ASSIGN_PEND:
4639     case REM_L1_SIG_ASSIGN_PEND:
4640       if(global_req == ASSIGN)
4641       {
4642         break;
4643       }
4644       else
4645       {
4646         dbug(1,dprintf("***L1 Req rem PLCI"));
4647         plci->internal_command = 0;
4648         sig_req(plci,REMOVE,0);
4649         send_req(plci);
4650       }
4651       break;
4652
4653       /* Call Deflection Request pending, just no appl ptr assigned */
4654     case CD_REQ_PEND:
4655       SSparms[1] = S_CALL_DEFLECTION;
4656       if(rc!=OK)
4657       {
4658         Info = 0x300E; /* not supported */
4659       }
4660       for(i=0; i<max_appl; i++)
4661       {
4662         if(application[i].CDEnable)
4663         {
4664           if(!application[i].Id) application[i].CDEnable = 0;
4665           else
4666           {
4667             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4668                   plci->number,"wws",Info,(word)3,SSparms);
4669             if(Info) application[i].CDEnable = 0;
4670           }
4671         }
4672       }
4673       plci->internal_command = 0;
4674       break;
4675
4676     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4677       return;
4678
4679     case PERM_COD_CALL:
4680       plci->internal_command = PERM_COD_CONN_PEND;
4681       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4682       return;
4683
4684     case PERM_COD_ASSIGN:
4685       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4686       plci->internal_command = 0;
4687       if(rc!=ASSIGN_OK) break;
4688       plci->internal_command = PERM_COD_CALL;
4689       sig_req(plci,CALL_REQ,0);
4690       send_req(plci);
4691       return;
4692
4693     case LISTEN_SIG_ASSIGN_PEND:
4694       if(rc == ASSIGN_OK)
4695       {
4696         plci->internal_command = 0;
4697         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4698         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4699         sig_req(plci,INDICATE_REQ,0);
4700         send_req(plci);
4701       }
4702       else
4703       {
4704         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4705         a->listen_active--;
4706         plci_remove(plci);
4707         plci->State = IDLE;
4708       }
4709       break;
4710
4711     case USELAW_REQ:
4712       if(global_req == ASSIGN)
4713       {
4714         if (rc==ASSIGN_OK)
4715       {
4716         sig_req(plci,LAW_REQ,0);
4717         send_req(plci);
4718         dbug(1,dprintf("Auto-Law assigned"));
4719         }
4720         else
4721         {
4722           dbug(1,dprintf("Auto-Law assign failed"));
4723           a->automatic_law = 3;
4724           plci->internal_command = 0;
4725           a->automatic_lawPLCI = 0;
4726         }
4727         break;
4728       }
4729       else if(req == LAW_REQ && rc==OK)
4730       {
4731         dbug(1,dprintf("Auto-Law initiated"));
4732         a->automatic_law = 2;
4733         plci->internal_command = 0;
4734       }
4735       else
4736       {
4737         dbug(1,dprintf("Auto-Law not supported"));
4738         a->automatic_law = 3;
4739         plci->internal_command = 0;
4740         sig_req(plci,REMOVE,0);
4741         send_req(plci);
4742         a->automatic_lawPLCI = 0;
4743       }
4744       break;
4745     }
4746     plci_remove_check(plci);
4747   }
4748 }
4749
4750 void data_rc(PLCI   * plci, byte ch)
4751 {
4752   dword Id;
4753   DIVA_CAPI_ADAPTER   * a;
4754   NCCI   *ncci_ptr;
4755   DATA_B3_DESC   *data;
4756   word ncci;
4757
4758   if (plci->appl)
4759   {
4760     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4761     a = plci->adapter;
4762     ncci = a->ch_ncci[ch];
4763     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4764     {
4765       ncci_ptr = &(a->ncci[ncci]);
4766       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4767       if (ncci_ptr->data_pending)
4768       {
4769         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4770         if (!(data->Flags &4) && a->ncci_state[ncci])
4771         {
4772           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4773           if(plci->tel) Id|=EXT_CONTROLLER;
4774           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4775                 "ww",data->Handle,0);
4776         }
4777         (ncci_ptr->data_out)++;
4778         if (ncci_ptr->data_out == MAX_DATA_B3)
4779           ncci_ptr->data_out = 0;
4780         (ncci_ptr->data_pending)--;
4781       }
4782     }
4783   }
4784 }
4785
4786 void data_ack(PLCI   * plci, byte ch)
4787 {
4788   dword Id;
4789   DIVA_CAPI_ADAPTER   * a;
4790   NCCI   *ncci_ptr;
4791   word ncci;
4792
4793   a = plci->adapter;
4794   ncci = a->ch_ncci[ch];
4795   ncci_ptr = &(a->ncci[ncci]);
4796   if (ncci_ptr->data_ack_pending)
4797   {
4798     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4799     {
4800       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4801       if(plci->tel) Id|=EXT_CONTROLLER;
4802       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4803             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4804     }
4805     (ncci_ptr->data_ack_out)++;
4806     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4807       ncci_ptr->data_ack_out = 0;
4808     (ncci_ptr->data_ack_pending)--;
4809   }
4810 }
4811
4812 void sig_ind(PLCI   * plci)
4813 {
4814   dword x_Id;
4815   dword Id;
4816   dword rId;
4817   word Number = 0;
4818   word i;
4819   word cip;
4820   dword cip_mask;
4821   byte   *ie;
4822   DIVA_CAPI_ADAPTER   * a;
4823     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4824 #define MAXPARMSIDS 31
4825     byte   * parms[MAXPARMSIDS];
4826     byte   * add_i[4];
4827     byte   * multi_fac_parms[MAX_MULTI_IE];
4828     byte   * multi_pi_parms [MAX_MULTI_IE];
4829     byte   * multi_ssext_parms [MAX_MULTI_IE];
4830     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4831
4832     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4833
4834   byte ai_len;
4835     byte   *esc_chi = "";
4836     byte   *esc_law = "";
4837     byte   *pty_cai = "";
4838     byte   *esc_cr  = "";
4839     byte   *esc_profile = "";
4840
4841     byte facility[256];
4842   PLCI   * tplci = 0;
4843   byte chi[] = "\x02\x18\x01";
4844   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4845     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4846   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4847   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4848   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4849   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4850     word parms_id[] =
4851          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4852           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4853           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4854           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4855           /* 14 FTY repl by ESC_CHI */
4856           /* 18 PI  repl by ESC_LAW */
4857          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4858      word multi_fac_id[] = {1, FTY};
4859      word multi_pi_id[]  = {1, PI};
4860      word multi_CiPN_id[]  = {1, OAD};
4861      word multi_ssext_id[]  = {1, ESC_SSEXT};
4862
4863      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4864
4865   byte   * cau;
4866   word ncci;
4867     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4868     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4869     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4870     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4871   byte force_mt_info = FALSE;
4872   byte dir;
4873   dword d;
4874   word w;
4875
4876   a = plci->adapter;
4877   Id = ((word)plci->Id<<8)|a->Id;
4878   WRITE_WORD(&SS_Ind[4],0x0000);
4879
4880   if (plci->sig_remove_id)
4881   {
4882     plci->Sig.RNR = 2; /* discard */
4883     dbug(1,dprintf("SIG discard while remove pending"));
4884     return;
4885   }
4886   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4887   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4888     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4889   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4890   {
4891     plci->Sig.RNR = 1;
4892     return;
4893   }
4894   if(plci->Sig.Ind==HANGUP && plci->channels)
4895   {
4896     plci->Sig.RNR = 1;
4897     plci->hangup_flow_ctrl_timer++;
4898     /* recover the network layer after timeout */
4899     if(plci->hangup_flow_ctrl_timer==100)
4900     {
4901       dbug(1,dprintf("Exceptional disc"));
4902       plci->Sig.RNR = 0;
4903       plci->hangup_flow_ctrl_timer = 0;
4904       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4905       {
4906         if (a->ncci_plci[ncci] == plci->Id)
4907         {
4908           cleanup_ncci_data (plci, ncci);
4909           if(plci->channels)plci->channels--;
4910           if (plci->appl)
4911             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4912         }
4913       }
4914       if (plci->appl)
4915         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4916       plci_remove(plci);
4917       plci->State=IDLE;
4918     }
4919     return;
4920   }
4921
4922   /* do first parse the info with no OAD in, because OAD will be converted */
4923   /* first the multiple facility IE, then mult. progress ind.              */
4924   /* then the parameters for the info_ind + conn_ind                       */
4925   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4926   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4927   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4928
4929   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4930
4931   IndParse(plci,parms_id,parms,0);
4932   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4933   esc_chi  = parms[14];
4934   esc_law  = parms[18];
4935   pty_cai  = parms[24];
4936   esc_cr   = parms[25];
4937   esc_profile = parms[27];
4938   if(esc_cr[0] && plci)
4939   {
4940     if(plci->cr_enquiry && plci->appl)
4941     {
4942       plci->cr_enquiry = FALSE;
4943       /* d = MANU_ID            */
4944       /* w = m_command          */
4945       /* b = total length       */
4946       /* b = indication type    */
4947       /* b = length of all IEs  */
4948       /* b = IE1                */
4949       /* S = IE1 length + cont. */
4950       /* b = IE2                */
4951       /* S = IE2 lenght + cont. */
4952       sendf(plci->appl,
4953         _MANUFACTURER_I,
4954         Id,
4955         0,
4956         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4957         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);
4958     }
4959   }
4960   /* create the additional info structure                                  */
4961   add_i[1] = parms[15]; /* KEY of additional info */
4962   add_i[2] = parms[11]; /* UUI of additional info */
4963   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4964
4965   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4966   /* indication returns by the card if requested by the function           */
4967   /* AutomaticLaw() after driver init                                      */
4968   if (a->automatic_law<4)
4969   {
4970     if(esc_law[0]){
4971       if(esc_law[2]){
4972         dbug(0,dprintf("u-Law selected"));
4973         a->u_law = 1;
4974       }
4975       else {
4976         dbug(0,dprintf("a-Law selected"));
4977         a->u_law = 0;
4978       }
4979       a->automatic_law = 4;
4980       if(plci==a->automatic_lawPLCI) {
4981         plci->internal_command = 0;
4982         sig_req(plci,REMOVE,0);
4983         send_req(plci);
4984         a->automatic_lawPLCI = 0;
4985       }
4986     }
4987     if (esc_profile[0])
4988     {
4989       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4990         UnMapController (a->Id), READ_DWORD (&esc_profile[6]),
4991         READ_DWORD (&esc_profile[10]), READ_DWORD (&esc_profile[14]),
4992         READ_DWORD (&esc_profile[18]), READ_DWORD (&esc_profile[46])));
4993
4994       a->profile.Global_Options &= 0x000000ffL;
4995       a->profile.B1_Protocols &= 0x000003ffL;
4996       a->profile.B2_Protocols &= 0x00001fdfL;
4997       a->profile.B3_Protocols &= 0x000000b7L;
4998
4999       a->profile.Global_Options &= READ_DWORD (&esc_profile[6]) |
5000         GL_BCHANNEL_OPERATION_SUPPORTED;
5001       a->profile.B1_Protocols &= READ_DWORD (&esc_profile[10]);
5002       a->profile.B2_Protocols &= READ_DWORD (&esc_profile[14]);
5003       a->profile.B3_Protocols &= READ_DWORD (&esc_profile[18]);
5004       a->manufacturer_features = READ_DWORD (&esc_profile[46]);
5005       a->man_profile.private_options = 0;
5006
5007       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5008       {
5009         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5010         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5011       }
5012
5013
5014       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5015         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5016       a->man_profile.rtp_primary_payloads = READ_DWORD (&esc_profile[50]);
5017       a->man_profile.rtp_additional_payloads = READ_DWORD (&esc_profile[54]);
5018
5019
5020       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5021         a->man_profile.private_options |= 1L << PRIVATE_T38;
5022
5023
5024       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5025         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5026
5027
5028       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5029         a->man_profile.private_options |= 1L << PRIVATE_V18;
5030
5031
5032       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5033         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5034
5035
5036       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5037         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5038
5039
5040       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5041         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5042
5043
5044       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5045         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5046
5047
5048       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5049         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5050
5051     }
5052     else
5053     {
5054       a->profile.Global_Options &= 0x0000007fL;
5055       a->profile.B1_Protocols &= 0x000003dfL;
5056       a->profile.B2_Protocols &= 0x00001adfL;
5057       a->profile.B3_Protocols &= 0x000000b7L;
5058       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5059     }
5060     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5061       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5062     {
5063       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5064     }
5065     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5066     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5067       UnMapController (a->Id), a->profile.Global_Options,
5068       a->profile.B1_Protocols, a->profile.B2_Protocols,
5069       a->profile.B3_Protocols, a->manufacturer_features));
5070   }
5071   /* codec plci for the handset/hook state support is just an internal id  */
5072   if(plci!=a->AdvCodecPLCI)
5073   {
5074     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5075     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5076     SendSSExtInd(0,plci,Id,multi_ssext_parms);
5077     SendInfo(plci,Id, parms, force_mt_info);
5078
5079     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5080
5081   }
5082
5083   /* switch the codec to the b-channel                                     */
5084   if(esc_chi[0] && plci && !plci->SuppState){
5085     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5086     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5087     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5088     if(plci->tel==ADV_VOICE && plci->appl) {
5089       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5090     }
5091   }
5092
5093   if(plci->appl) Number = plci->appl->Number++;
5094
5095   switch(plci->Sig.Ind) {
5096   /* Response to Get_Supported_Services request */
5097   case S_SUPPORTED:
5098     dbug(1,dprintf("S_Supported"));
5099     if(!plci->appl) break;
5100     if(pty_cai[0]==4)
5101     {
5102       WRITE_DWORD(&CF_Ind[6],READ_DWORD(&pty_cai[1]) );
5103     }
5104     else
5105     {
5106       WRITE_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5107     }
5108     WRITE_WORD (&CF_Ind[1], 0);
5109     WRITE_WORD (&CF_Ind[4], 0);
5110     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5111     plci_remove(plci);
5112     break;
5113                     
5114   /* Supplementary Service rejected */
5115   case S_SERVICE_REJ:
5116     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5117     if(!pty_cai[0]) break;
5118     switch (pty_cai[5])
5119     {
5120     case ECT_EXECUTE:
5121     case THREE_PTY_END:
5122     case THREE_PTY_BEGIN:
5123       if(!plci->relatedPTYPLCI) break;
5124       tplci = plci->relatedPTYPLCI;
5125       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5126       if(tplci->tel) rId|=EXT_CONTROLLER;
5127       if(pty_cai[5]==ECT_EXECUTE)
5128       {
5129         WRITE_WORD(&SS_Ind[1],S_ECT);
5130
5131         plci->vswitchstate=0;
5132         plci->relatedPTYPLCI->vswitchstate=0;
5133
5134       }
5135       else
5136       {
5137         WRITE_WORD(&SS_Ind[1],pty_cai[5]+3);
5138       }
5139       if(pty_cai[2]!=0xff)
5140       {
5141         WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5142       }
5143       else
5144       {
5145         WRITE_WORD(&SS_Ind[4],0x300E);
5146       }
5147       plci->relatedPTYPLCI = 0;
5148       plci->ptyState = 0;
5149       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5150       break;
5151
5152     case CALL_DEFLECTION:
5153       if(pty_cai[2]!=0xff)
5154       {
5155         WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5156       }
5157       else
5158       {
5159         WRITE_WORD(&SS_Ind[4],0x300E);
5160       }
5161       WRITE_WORD(&SS_Ind[1],pty_cai[5]);
5162       for(i=0; i<max_appl; i++)
5163       {
5164         if(application[i].CDEnable)
5165         {
5166           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5167           application[i].CDEnable = FALSE;
5168         }
5169       }
5170       break;
5171
5172     case DEACTIVATION_DIVERSION:
5173     case ACTIVATION_DIVERSION:
5174     case DIVERSION_INTERROGATE_CFU:
5175     case DIVERSION_INTERROGATE_CFB:
5176     case DIVERSION_INTERROGATE_CFNR:
5177     case DIVERSION_INTERROGATE_NUM:
5178     case CCBS_REQUEST:
5179     case CCBS_DEACTIVATE:
5180     case CCBS_INTERROGATE:
5181       if(!plci->appl) break;
5182       if(pty_cai[2]!=0xff)
5183       {
5184         WRITE_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5185       }
5186       else
5187       {
5188         WRITE_WORD(&Interr_Err_Ind[4],0x300E);
5189       }
5190       switch (pty_cai[5])
5191       {
5192         case DEACTIVATION_DIVERSION:
5193           dbug(1,dprintf("Deact_Div"));
5194           Interr_Err_Ind[0]=0x9;
5195           Interr_Err_Ind[3]=0x6;
5196           WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5197           break;
5198         case ACTIVATION_DIVERSION:
5199           dbug(1,dprintf("Act_Div"));
5200           Interr_Err_Ind[0]=0x9;
5201           Interr_Err_Ind[3]=0x6;
5202           WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5203           break;
5204         case DIVERSION_INTERROGATE_CFU:
5205         case DIVERSION_INTERROGATE_CFB:
5206         case DIVERSION_INTERROGATE_CFNR:
5207           dbug(1,dprintf("Interr_Div"));
5208           Interr_Err_Ind[0]=0xa;
5209           Interr_Err_Ind[3]=0x7;
5210           WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5211           break;
5212         case DIVERSION_INTERROGATE_NUM:
5213           dbug(1,dprintf("Interr_Num"));
5214           Interr_Err_Ind[0]=0xa;
5215           Interr_Err_Ind[3]=0x7;
5216           WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5217           break;
5218         case CCBS_REQUEST:
5219           dbug(1,dprintf("CCBS Request"));
5220           Interr_Err_Ind[0]=0xd;
5221           Interr_Err_Ind[3]=0xa;
5222           WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5223           break;
5224         case CCBS_DEACTIVATE:
5225           dbug(1,dprintf("CCBS Deactivate"));
5226           Interr_Err_Ind[0]=0x9;
5227           Interr_Err_Ind[3]=0x6;
5228           WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5229           break;
5230         case CCBS_INTERROGATE:
5231           dbug(1,dprintf("CCBS Interrogate"));
5232           Interr_Err_Ind[0]=0xb;
5233           Interr_Err_Ind[3]=0x8;
5234           WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5235           break;
5236       }
5237       WRITE_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5238       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5239       plci_remove(plci);
5240       break;
5241     case ACTIVATION_MWI:      
5242     case DEACTIVATION_MWI:
5243       if(pty_cai[5]==ACTIVATION_MWI)
5244       {
5245         WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5246       }
5247       else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5248       
5249       if(pty_cai[2]!=0xff)
5250       {
5251         WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5252       }
5253       else
5254       {
5255         WRITE_WORD(&SS_Ind[4],0x300E);
5256       }
5257
5258       if(plci->cr_enquiry)
5259       {
5260         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5261         plci_remove(plci);
5262       }
5263       else
5264       {
5265         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5266       }
5267       break;
5268     case CONF_ADD: /* ERROR */
5269     case CONF_BEGIN:
5270     case CONF_DROP:
5271     case CONF_ISOLATE:
5272     case CONF_REATTACH:
5273       CONF_Ind[0]=9;
5274       CONF_Ind[3]=6;   
5275       switch(pty_cai[5])
5276       {
5277       case CONF_BEGIN:
5278           WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5279           plci->ptyState = 0;
5280           break;
5281       case CONF_DROP:
5282           CONF_Ind[0]=5;
5283           CONF_Ind[3]=2;
5284           WRITE_WORD(&CONF_Ind[1],S_CONF_DROP);
5285           plci->ptyState = CONNECTED;
5286           break;
5287       case CONF_ISOLATE:
5288           CONF_Ind[0]=5;
5289           CONF_Ind[3]=2;
5290           WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5291           plci->ptyState = CONNECTED;
5292           break;
5293       case CONF_REATTACH:
5294           CONF_Ind[0]=5;
5295           CONF_Ind[3]=2;
5296           WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5297           plci->ptyState = CONNECTED;
5298           break;
5299       case CONF_ADD:
5300           WRITE_WORD(&CONF_Ind[1],S_CONF_ADD);
5301           plci->relatedPTYPLCI = 0;
5302           tplci=plci->relatedPTYPLCI;
5303           if(tplci) tplci->ptyState = CONNECTED;
5304           plci->ptyState = CONNECTED;
5305           break;
5306       }
5307           
5308       if(pty_cai[2]!=0xff)
5309       {
5310         WRITE_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5311       }
5312       else
5313       {
5314         WRITE_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5315                                             within the required time */
5316       }
5317
5318       WRITE_DWORD(&CONF_Ind[6],0x0);
5319       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5320       break;
5321     }
5322     break;
5323
5324   /* Supplementary Service indicates success */
5325   case S_SERVICE:
5326     dbug(1,dprintf("Service_Ind"));
5327     WRITE_WORD (&CF_Ind[4], 0);
5328     switch (pty_cai[5])
5329     {
5330     case THREE_PTY_END:
5331     case THREE_PTY_BEGIN:
5332     case ECT_EXECUTE:
5333       if(!plci->relatedPTYPLCI) break;
5334       tplci = plci->relatedPTYPLCI;
5335       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5336       if(tplci->tel) rId|=EXT_CONTROLLER;
5337       if(pty_cai[5]==ECT_EXECUTE)
5338       {
5339         WRITE_WORD(&SS_Ind[1],S_ECT);
5340
5341         if(plci->vswitchstate!=3)
5342         {
5343
5344         plci->ptyState = IDLE;
5345         plci->relatedPTYPLCI = 0;
5346         plci->ptyState = 0;
5347
5348         }
5349
5350         dbug(1,dprintf("ECT OK"));
5351         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5352
5353
5354
5355       }
5356       else
5357       {
5358         switch (plci->ptyState)
5359         {
5360         case S_3PTY_BEGIN:
5361           plci->ptyState = CONNECTED;
5362           dbug(1,dprintf("3PTY ON"));
5363           break;
5364
5365         case S_3PTY_END:
5366           plci->ptyState = IDLE;
5367           plci->relatedPTYPLCI = 0;
5368           plci->ptyState = 0;
5369           dbug(1,dprintf("3PTY OFF"));
5370           break;
5371         }
5372         WRITE_WORD(&SS_Ind[1],pty_cai[5]+3);
5373         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5374       }
5375       break;
5376
5377     case CALL_DEFLECTION:
5378       WRITE_WORD(&SS_Ind[1],pty_cai[5]);
5379       for(i=0; i<max_appl; i++)
5380       {
5381         if(application[i].CDEnable)
5382         {
5383           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5384           application[i].CDEnable = FALSE;
5385         }
5386       }
5387       break;
5388
5389     case DEACTIVATION_DIVERSION:
5390     case ACTIVATION_DIVERSION:
5391       if(!plci->appl) break;
5392       WRITE_WORD(&CF_Ind[1],pty_cai[5]+2);
5393       WRITE_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5394       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5395       plci_remove(plci);
5396       break;
5397
5398     case DIVERSION_INTERROGATE_CFU:
5399     case DIVERSION_INTERROGATE_CFB:
5400     case DIVERSION_INTERROGATE_CFNR:
5401     case DIVERSION_INTERROGATE_NUM:
5402     case CCBS_REQUEST:
5403     case CCBS_DEACTIVATE:
5404     case CCBS_INTERROGATE:
5405       if(!plci->appl) break;
5406       switch (pty_cai[5])
5407       {
5408         case DIVERSION_INTERROGATE_CFU:
5409         case DIVERSION_INTERROGATE_CFB:
5410         case DIVERSION_INTERROGATE_CFNR:
5411           dbug(1,dprintf("Interr_Div"));
5412           WRITE_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5413           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5414           break;
5415         case DIVERSION_INTERROGATE_NUM:
5416           dbug(1,dprintf("Interr_Num"));
5417           WRITE_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5418           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5419           break;
5420         case CCBS_REQUEST:
5421           dbug(1,dprintf("CCBS Request"));
5422           WRITE_WORD(&pty_cai[1],S_CCBS_REQUEST);
5423           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5424           break;
5425         case CCBS_DEACTIVATE:
5426           dbug(1,dprintf("CCBS Deactivate"));
5427           WRITE_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5428           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5429           break;
5430         case CCBS_INTERROGATE:
5431           dbug(1,dprintf("CCBS Interrogate"));
5432           WRITE_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5433           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5434           break;
5435       }
5436       WRITE_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5437       WRITE_DWORD(&pty_cai[6],plci->appl->S_Handle);
5438       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5439       plci_remove(plci);
5440       break;
5441
5442     case ACTIVATION_MWI:
5443     case DEACTIVATION_MWI:
5444       if(pty_cai[5]==ACTIVATION_MWI)
5445       {
5446         WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5447       }
5448       else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5449       if(plci->cr_enquiry)
5450       {
5451         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5452         plci_remove(plci);
5453       }
5454       else
5455       {
5456         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5457       }
5458       break;
5459     case MWI_INDICATION:
5460       if(pty_cai[0]>=0x12)
5461       {
5462         WRITE_WORD(&pty_cai[3],S_MWI_INDICATE);
5463         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5464         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5465         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5466         {
5467           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5468           {
5469             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5470             plci_remove(plci);
5471             return;
5472           }
5473           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5474           pty_cai[0]=0;
5475         }
5476         else
5477         {
5478           for(i=0; i<max_appl; i++)
5479           {                     
5480             if(a->Notification_Mask[i]&SMASK_MWI)
5481             {
5482               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5483               pty_cai[0]=0;
5484             }
5485           }
5486         }
5487
5488         if(!pty_cai[0])
5489         { /* acknowledge */
5490           facility[2]= 0; /* returncode */
5491         }
5492         else facility[2]= 0xff;
5493       }
5494       else
5495       {
5496         /* reject */
5497         facility[2]= 0xff; /* returncode */
5498       }
5499       facility[0]= 2;
5500       facility[1]= MWI_RESPONSE; /* Function */
5501       add_p(plci,CAI,facility);
5502       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5503       sig_req(plci,S_SERVICE,0);
5504       send_req(plci);
5505       plci->command = 0;
5506       next_internal_command (Id, plci);
5507       break;
5508     case CONF_ADD: /* OK */
5509     case CONF_BEGIN:
5510     case CONF_DROP:
5511     case CONF_ISOLATE:
5512     case CONF_REATTACH:
5513     case CONF_PARTYDISC:
5514       CONF_Ind[0]=9;
5515       CONF_Ind[3]=6;
5516       switch(pty_cai[5])
5517       {
5518       case CONF_BEGIN:
5519           WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5520           if(pty_cai[0]==6)
5521           {
5522               d=pty_cai[6];
5523               WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */
5524           }
5525           else
5526           {
5527               WRITE_DWORD(&CONF_Ind[6],0x0);
5528           }
5529           break;
5530       case CONF_ISOLATE:
5531           WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5532           CONF_Ind[0]=5;
5533           CONF_Ind[3]=2;
5534           break;
5535       case CONF_REATTACH:
5536           WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5537           CONF_Ind[0]=5;
5538           CONF_Ind[3]=2;
5539           break;
5540       case CONF_DROP:
5541           WRITE_WORD(&CONF_Ind[1],S_CONF_DROP);
5542           CONF_Ind[0]=5;
5543           CONF_Ind[3]=2;
5544           break;
5545       case CONF_ADD:
5546           WRITE_WORD(&CONF_Ind[1],S_CONF_ADD);
5547           d=pty_cai[6];
5548           WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */
5549           tplci=plci->relatedPTYPLCI;
5550           if(tplci) tplci->ptyState = CONNECTED;
5551           break;
5552       case CONF_PARTYDISC:
5553           CONF_Ind[0]=7;
5554           CONF_Ind[3]=4;          
5555           WRITE_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5556           d=pty_cai[6];
5557           WRITE_DWORD(&CONF_Ind[4],d); /* PartyID */
5558           break;
5559       }
5560       plci->ptyState = CONNECTED;
5561       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5562       break;
5563     case CCBS_INFO_RETAIN:
5564     case CCBS_ERASECALLLINKAGEID:
5565     case CCBS_STOP_ALERTING:
5566       CONF_Ind[0]=5;
5567       CONF_Ind[3]=2;
5568       switch(pty_cai[5])
5569       {
5570       case CCBS_INFO_RETAIN:
5571         WRITE_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5572         break;
5573       case CCBS_STOP_ALERTING:
5574         WRITE_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5575     break;
5576       case CCBS_ERASECALLLINKAGEID:
5577         WRITE_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5578         CONF_Ind[0]=7;
5579         CONF_Ind[3]=4;
5580         CONF_Ind[6]=0;
5581         CONF_Ind[7]=0;
5582         break;
5583       }      
5584       w=pty_cai[6];
5585       WRITE_WORD(&CONF_Ind[4],w); /* PartyID */
5586
5587       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5588       {
5589         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5590       }
5591       else
5592       {
5593         for(i=0; i<max_appl; i++)
5594             if(a->Notification_Mask[i]&SMASK_CCBS)
5595                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5596       }
5597       break;
5598     }
5599     break;
5600   case CALL_HOLD_REJ:
5601     cau = parms[7];
5602     if(cau)
5603     {
5604       i = _L3_CAUSE | cau[2];
5605       if(cau[2]==0) i = 0x3603;
5606     }
5607     else
5608     {
5609       i = 0x3603;
5610     }
5611     WRITE_WORD(&SS_Ind[1],S_HOLD);
5612     WRITE_WORD(&SS_Ind[4],i);
5613     if(plci->SuppState == HOLD_REQUEST)
5614     {
5615       plci->SuppState = IDLE;
5616       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5617     }
5618     break;
5619
5620   case CALL_HOLD_ACK:
5621     if(plci->SuppState == HOLD_REQUEST)
5622     {
5623       plci->SuppState = CALL_HELD;
5624       CodecIdCheck(a, plci);
5625       start_internal_command (Id, plci, hold_save_command);
5626     }
5627     break;
5628
5629   case CALL_RETRIEVE_REJ:
5630     cau = parms[7];
5631     if(cau)
5632     {
5633       i = _L3_CAUSE | cau[2];
5634       if(cau[2]==0) i = 0x3603;
5635     }
5636     else
5637     {
5638       i = 0x3603;
5639     }
5640     WRITE_WORD(&SS_Ind[1],S_RETRIEVE);
5641     WRITE_WORD(&SS_Ind[4],i);
5642     if(plci->SuppState == RETRIEVE_REQUEST)
5643     {
5644       plci->SuppState = CALL_HELD;
5645       CodecIdCheck(a, plci);
5646       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5647     }
5648     break;
5649
5650   case CALL_RETRIEVE_ACK:
5651     WRITE_WORD(&SS_Ind[1],S_RETRIEVE);
5652     if(plci->SuppState == RETRIEVE_REQUEST)
5653     {
5654       plci->SuppState = IDLE;
5655       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5656       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5657       if(plci->tel)
5658       {
5659         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5660         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5661         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5662         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5663         {
5664           dbug(1,dprintf("Get B-ch"));
5665           start_internal_command (Id, plci, retrieve_restore_command);
5666         }
5667         else
5668           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5669       }
5670       else
5671         start_internal_command (Id, plci, retrieve_restore_command);
5672     }
5673     break;
5674
5675   case INDICATE_IND:
5676     if(plci->State != LISTENING) {
5677       sig_req(plci,HANGUP,0);
5678       send_req(plci);
5679       break;
5680     }
5681     cip = find_cip(a,parms[4],parms[6]);
5682     cip_mask = 1L<<cip;
5683     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5684     clear_c_ind_mask (plci);
5685     if (!remove_started && !a->adapter_disabled)
5686     {
5687       set_c_ind_mask_bit (plci, MAX_APPL);
5688       group_optimization(a, plci);
5689       for(i=0; i<max_appl; i++) {
5690         if(application[i].Id
5691         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5692         && CPN_filter_ok(parms[0],a,i)
5693         && test_group_ind_mask_bit (plci, i) ) {
5694           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5695           set_c_ind_mask_bit (plci, i);
5696           dump_c_ind_mask (plci);
5697           plci->State = INC_CON_PENDING;
5698           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5699             CALL_DIR_IN | CALL_DIR_ANSWER;
5700           if(esc_chi[0]) {
5701             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5702             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5703           }
5704           /* if a listen on the ext controller is done, check if hook states */
5705           /* are supported or if just a on board codec must be activated     */
5706           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5707             if(a->profile.Global_Options & HANDSET)
5708               plci->tel = ADV_VOICE;
5709             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5710               plci->tel = CODEC;
5711             if(plci->tel) Id|=EXT_CONTROLLER;
5712             a->codec_listen[i] = plci;
5713           }
5714
5715           sendf(&application[i],_CONNECT_I,Id,0,
5716                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5717                              parms[0],    /* CalledPartyNumber   */
5718                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5719                              parms[2],    /* CalledPartySubad    */
5720                              parms[3],    /* CallingPartySubad   */
5721                              parms[4],    /* BearerCapability    */
5722                              parms[5],    /* LowLC               */
5723                              parms[6],    /* HighLC              */
5724                              ai_len,      /* nested struct add_i */
5725                              add_i[0],    /* B channel info    */
5726                              add_i[1],    /* keypad facility   */
5727                              add_i[2],    /* user user data    */
5728                              add_i[3],    /* nested facility   */
5729                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5730                              );
5731           SendSSExtInd(&application[i],
5732                         plci,
5733                         Id,
5734                         multi_ssext_parms);
5735           SendSetupInfo(&application[i],
5736                         plci,
5737                         Id,
5738                         parms,
5739                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE));
5740         }
5741       }
5742       clear_c_ind_mask_bit (plci, MAX_APPL);
5743       dump_c_ind_mask (plci);
5744     }
5745     if(c_ind_mask_empty (plci)) {
5746       sig_req(plci,HANGUP,0);
5747       send_req(plci);
5748       plci->State = IDLE;
5749     }
5750     plci->notifiedcall = 0;
5751     a->listen_active--;
5752     listen_check(a);
5753     break;
5754
5755   case CALL_PEND_NOTIFY:
5756     plci->notifiedcall = 1;
5757     listen_check(a);
5758     break;
5759
5760   case CALL_IND:
5761   case CALL_CON:
5762     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5763     {
5764       if(plci->internal_command==PERM_COD_CONN_PEND)
5765       {
5766         if(plci->State==ADVANCED_VOICE_NOSIG)
5767         {
5768           dbug(1,dprintf("***Codec OK"));
5769           if(a->AdvSignalPLCI)
5770           {
5771             tplci = a->AdvSignalPLCI;
5772             if(tplci->spoofed_msg)
5773             {
5774               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5775               tplci->command = 0;
5776               tplci->internal_command = 0;
5777               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5778               switch (tplci->spoofed_msg)
5779               {
5780               case CALL_RES:
5781                 tplci->command = _CONNECT_I|RESPONSE;
5782                 api_load_msg (&tplci->saved_msg, saved_parms);
5783                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5784                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5785                 {
5786                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5787                   add_p(tplci,LLI,"\x01\x01");
5788                 }
5789                 add_s(tplci, CONN_NR, &saved_parms[2]);
5790                 add_s(tplci, LLC, &saved_parms[4]);
5791                 add_ai(tplci, &saved_parms[5]);
5792                 tplci->State = INC_CON_ACCEPT;
5793                 sig_req(tplci, CALL_RES,0);
5794                 send_req(tplci);
5795                 break;
5796
5797               case AWAITING_SELECT_B:
5798                 dbug(1,dprintf("Select_B continue"));
5799                 start_internal_command (x_Id, tplci, select_b_command);
5800                 break;
5801
5802               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5803                 if(!tplci->Sig.Id)
5804                 {
5805                   dbug(1,dprintf("No SigID!"));
5806                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5807                   plci_remove(tplci);
5808                   break;
5809                 }
5810                 tplci->command = _MANUFACTURER_R;
5811                 api_load_msg (&tplci->saved_msg, saved_parms);
5812                 dir = saved_parms[2].info[0];
5813                 if(dir==1) {
5814                   sig_req(tplci,CALL_REQ,0);
5815                 }
5816                 else if(!dir){
5817                   sig_req(tplci,LISTEN_REQ,0);
5818                 }
5819                 send_req(tplci);
5820                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5821                 break;
5822
5823               case (CALL_REQ|AWAITING_MANUF_CON):
5824                 sig_req(tplci,CALL_REQ,0);
5825                 send_req(tplci);
5826                 break;
5827
5828               case CALL_REQ:
5829                 if(!tplci->Sig.Id)
5830                 {
5831                   dbug(1,dprintf("No SigID!"));
5832                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5833                   plci_remove(tplci);
5834                   break;
5835                 }
5836                 tplci->command = _CONNECT_R;
5837                 api_load_msg (&tplci->saved_msg, saved_parms);
5838                 add_s(tplci,CPN,&saved_parms[1]);
5839                 add_s(tplci,DSA,&saved_parms[3]);
5840                 add_ai(tplci,&saved_parms[9]);
5841                 sig_req(tplci,CALL_REQ,0);
5842                 send_req(tplci);
5843                 break;
5844
5845               case CALL_RETRIEVE:
5846                 tplci->command = C_RETRIEVE_REQ;
5847                 sig_req(tplci,CALL_RETRIEVE,0);
5848                 send_req(tplci);
5849                 break;
5850               }
5851               tplci->spoofed_msg = 0;
5852               if (tplci->internal_command == 0)
5853                 next_internal_command (x_Id, tplci);
5854             }
5855           }
5856           next_internal_command (Id, plci);
5857           break;
5858         }
5859         dbug(1,dprintf("***Codec Hook Init Req"));
5860         plci->internal_command = PERM_COD_HOOK;
5861         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5862         sig_req(plci,TEL_CTRL,0);
5863         send_req(plci);
5864       }
5865     }
5866     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5867     && plci->State!=INC_ACT_PENDING)
5868     {
5869       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5870       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5871       {
5872         chi[2] = plci->b_channel;
5873         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5874       }
5875       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5876       plci->State = INC_ACT_PENDING;
5877     }
5878     break;
5879
5880   case TEL_CTRL:
5881     Number = 0;
5882     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5883     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5884       switch (ie[1]&0x91) {
5885         case 0x80:   /* hook off */
5886         case 0x81:
5887           if(plci->internal_command==PERM_COD_HOOK)
5888           {
5889             dbug(1,dprintf("init:hook_off"));
5890             plci->hook_state = ie[1];
5891             next_internal_command (Id, plci);
5892             break;
5893           }
5894           else /* ignore doubled hook indications */
5895           {
5896             if( ((plci->hook_state)&0xf0)==0x80)
5897             {
5898               dbug(1,dprintf("ignore hook"));
5899               break;
5900             }
5901             plci->hook_state = ie[1]&0x91;
5902           }
5903           /* check for incoming call pending */
5904           /* and signal '+'.Appl must decide */
5905           /* with connect_res if call must   */
5906           /* accepted or not                 */
5907           for(i=0, tplci=0;i<max_appl;i++){
5908             if(a->codec_listen[i]
5909             && (a->codec_listen[i]->State==INC_CON_PENDING
5910               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5911               tplci = a->codec_listen[i];
5912               tplci->appl = &application[i];
5913             }
5914           }
5915           /* no incoming call, do outgoing call */
5916           /* and signal '+' if outg. setup   */
5917           if(!a->AdvSignalPLCI && !tplci){
5918             if((i=get_plci(a))) {
5919               a->AdvSignalPLCI = &a->plci[i-1];
5920               tplci = a->AdvSignalPLCI;
5921               tplci->tel  = ADV_VOICE;
5922               WRITE_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5923               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5924                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5925                 add_p(tplci,LLI,"\x01\x01");
5926               }
5927               add_p(tplci, CAI, voice_cai);
5928               add_p(tplci, OAD, a->TelOAD);
5929               add_p(tplci, OSA, a->TelOSA);
5930               add_p(tplci,SHIFT|6,0);
5931               add_p(tplci,SIN,"\x02\x01\x00");
5932               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5933               sig_req(tplci,ASSIGN,DSIG_ID);
5934               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5935               a->AdvSignalPLCI->command = 0;
5936               tplci->appl = a->AdvSignalAppl;
5937               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5938               send_req(tplci);
5939             }
5940
5941           }
5942
5943           if(!tplci) break;
5944           Id = ((word)tplci->Id<<8)|a->Id;
5945           Id|=EXT_CONTROLLER;
5946           sendf(tplci->appl,
5947                 _FACILITY_I,
5948                 Id,
5949                 0,
5950                 "ws", (word)0, "\x01+");
5951           break;
5952
5953         case 0x90:   /* hook on  */
5954         case 0x91:
5955           if(plci->internal_command==PERM_COD_HOOK)
5956           {
5957             dbug(1,dprintf("init:hook_on"));
5958             plci->hook_state = ie[1]&0x91;
5959             next_internal_command (Id, plci);
5960             break;
5961           }
5962           else /* ignore doubled hook indications */
5963           {
5964             if( ((plci->hook_state)&0xf0)==0x90) break;
5965             plci->hook_state = ie[1]&0x91;
5966           }
5967           /* hangup the adv. voice call and signal '-' to the appl */
5968           if(a->AdvSignalPLCI) {
5969             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5970             if(plci->tel) Id|=EXT_CONTROLLER;
5971             sendf(a->AdvSignalAppl,
5972                   _FACILITY_I,
5973                   Id,
5974                   0,
5975                   "ws", (word)0, "\x01-");
5976             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5977             a->AdvSignalPLCI->command = 0;
5978             sig_req(a->AdvSignalPLCI,HANGUP,0);
5979             send_req(a->AdvSignalPLCI);
5980           }
5981           break;
5982       }
5983     }
5984     break;
5985
5986   case RESUME:
5987     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5988     WRITE_WORD(&resume_cau[4],GOOD);
5989     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5990     break;
5991
5992   case SUSPEND:
5993     clear_c_ind_mask (plci);
5994
5995     if (plci->NL.Id && !plci->nl_remove_id) {
5996       mixer_remove (plci);
5997       nl_req_ncci(plci,REMOVE,0);
5998     }
5999     if (!plci->sig_remove_id) {
6000       plci->internal_command = 0;
6001       sig_req(plci,REMOVE,0);
6002     }
6003     send_req(plci);
6004     if(!plci->channels) {
6005       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6006       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6007     }
6008     break;
6009
6010   case SUSPEND_REJ:
6011     break;
6012
6013   case HANGUP:
6014     plci->hangup_flow_ctrl_timer=0;
6015     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6016     cau = parms[7];
6017     if(cau) {
6018       i = _L3_CAUSE | cau[2];
6019       if(cau[2]==0) i = 0;
6020       else if(cau[2]==8) i = _L1_ERROR;
6021       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6022       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6023     }
6024     else {
6025       i = _L3_ERROR;
6026     }
6027
6028     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6029     {
6030       for(i=0; i<max_appl; i++)
6031       {
6032         if(test_c_ind_mask_bit (plci, i))
6033           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6034       }
6035     }
6036     else
6037     {
6038       clear_c_ind_mask (plci);
6039     }
6040     if(!plci->appl)
6041     {
6042       if (plci->State == LISTENING)
6043       {
6044         plci->notifiedcall=0;
6045         a->listen_active--;
6046       }
6047       plci->State = INC_DIS_PENDING;
6048       if(c_ind_mask_empty (plci))
6049       {
6050         plci->State = IDLE;
6051         if (plci->NL.Id && !plci->nl_remove_id)
6052         {
6053           mixer_remove (plci);
6054           nl_req_ncci(plci,REMOVE,0);
6055         }
6056         if (!plci->sig_remove_id)
6057         {
6058           plci->internal_command = 0;
6059           sig_req(plci,REMOVE,0);
6060         }
6061         send_req(plci);
6062       }
6063     }
6064     else
6065     {
6066         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6067         /* result in a second HANGUP! Don't generate another        */
6068         /* DISCONNECT                                               */
6069       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6070       {
6071         if(plci->State==RESUMING)
6072         {
6073           WRITE_WORD(&resume_cau[4],i);
6074           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6075         }
6076         plci->State = INC_DIS_PENDING;
6077         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6078       }
6079     }
6080     break;
6081
6082   case SSEXT_IND:
6083     SendSSExtInd(0,plci,Id,multi_ssext_parms);
6084     break;
6085
6086   case VSWITCH_REQ:
6087     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6088     break;
6089   case VSWITCH_IND:
6090  if(plci->relatedPTYPLCI &&
6091   plci->vswitchstate==3 &&
6092   plci->relatedPTYPLCI->vswitchstate==3 &&
6093   parms[MAXPARMSIDS-1][0])
6094  {
6095   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6096   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6097   send_req(plci->relatedPTYPLCI);
6098  }
6099     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6100     break;
6101
6102   }
6103 }
6104
6105
6106 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6107 {
6108   word i;
6109   byte   * ie;
6110   word Info_Number;
6111   byte   * Info_Element;
6112   word Info_Mask = 0;
6113
6114   dbug(1,dprintf("SetupInfo"));
6115
6116   for(i=0; i<MAXPARMSIDS; i++) {
6117     ie = parms[i];
6118     Info_Number = 0;
6119     Info_Element = ie;
6120     if(ie[0]) {
6121       switch(i) {
6122       case 0:
6123         dbug(1,dprintf("CPN "));
6124         Info_Number = 0x0070;
6125         Info_Mask   = 0x80;
6126         Info_Sent_Flag = TRUE;
6127         break;
6128       case 8:  /* display      */
6129         dbug(1,dprintf("display(%d)",i));
6130         Info_Number = 0x0028;
6131         Info_Mask = 0x04;
6132         Info_Sent_Flag = TRUE;
6133         break;
6134       case 16: /* Channel Id */
6135         dbug(1,dprintf("CHI"));
6136         Info_Number = 0x0018;
6137         Info_Mask = 0x100;
6138         Info_Sent_Flag = TRUE;
6139         mixer_set_bchannel_id (plci, Info_Element);
6140         break;
6141       case 19: /* Redirected Number */
6142         dbug(1,dprintf("RDN"));
6143         Info_Number = 0x0074;
6144         Info_Mask = 0x400;
6145         Info_Sent_Flag = TRUE;
6146         break;
6147       case 20: /* Redirected Number extended */
6148         dbug(1,dprintf("RDX"));
6149         Info_Number = 0x0073;
6150         Info_Mask = 0x400;
6151         Info_Sent_Flag = TRUE;
6152         break;
6153       case 22: /* Redirecing Number  */
6154         dbug(1,dprintf("RIN"));
6155         Info_Number = 0x0076;
6156         Info_Mask = 0x400;
6157         Info_Sent_Flag = TRUE;
6158         break;
6159       default:
6160         Info_Number = 0;
6161         break;
6162       }
6163     }
6164
6165     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6166       Info_Number = 0x8000 |5;
6167       Info_Mask = 0x10;
6168       Info_Element = "";
6169     }
6170
6171     if(Info_Sent_Flag && Info_Number){
6172       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6173         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6174       }
6175     }
6176   }
6177 }
6178
6179
6180 void SendInfo(PLCI   * plci, dword Id, byte   * * parms, byte iesent)
6181 {
6182   word i;
6183   word j;
6184   word k;
6185   byte   * ie;
6186   word Info_Number;
6187   byte   * Info_Element;
6188   word Info_Mask = 0;
6189   static byte charges[5] = {4,0,0,0,0};
6190   static byte cause[] = {0x02,0x80,0x00};
6191   APPL   *appl;
6192
6193   dbug(1,dprintf("InfoParse "));
6194
6195   if(
6196         !plci->appl
6197         && !plci->State
6198         && plci->Sig.Ind!=NCR_FACILITY
6199       )
6200   {
6201     dbug(1,dprintf("NoParse "));
6202     return;
6203   }
6204   cause[2] = 0;
6205   for(i=0; i<MAXPARMSIDS; i++) {
6206     ie = parms[i];
6207     Info_Number = 0;
6208     Info_Element = ie;
6209     if(ie[0]) {
6210       switch(i) {
6211       case 0:
6212         dbug(1,dprintf("CPN "));
6213         Info_Number = 0x0070;
6214         Info_Mask   = 0x80;
6215         break;
6216       case 7: /* ESC_CAU */
6217         dbug(1,dprintf("cau(0x%x)",ie[2]));
6218         Info_Number = 0x0008;
6219         Info_Mask = 0x00;
6220         cause[2] = ie[2];
6221         Info_Element = 0;
6222         break;
6223       case 8:  /* display      */
6224         dbug(1,dprintf("display(%d)",i));
6225         Info_Number = 0x0028;
6226         Info_Mask = 0x04;
6227         break;
6228       case 9:  /* Date display */
6229         dbug(1,dprintf("date(%d)",i));
6230         Info_Number = 0x0029;
6231         Info_Mask = 0x02;
6232         break;
6233       case 10: /* charges */
6234         for(j=0;j<4;j++) charges[1+j] = 0;
6235         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6236         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6237         Info_Number = 0x4000;
6238         Info_Mask = 0x40;
6239         Info_Element = charges;
6240         break;
6241       case 11: /* user user info */
6242         dbug(1,dprintf("uui"));
6243         Info_Number = 0x007E;
6244         Info_Mask = 0x08;
6245         break;
6246       case 12: /* congestion receiver ready */
6247         dbug(1,dprintf("clRDY"));
6248         Info_Number = 0x00B0;
6249         Info_Mask = 0x08;
6250         Info_Element = "";
6251         break;
6252       case 13: /* congestion receiver not ready */
6253         dbug(1,dprintf("clNRDY"));
6254         Info_Number = 0x00BF;
6255         Info_Mask = 0x08;
6256         Info_Element = "";
6257         break;
6258       case 15: /* Keypad Facility */
6259         dbug(1,dprintf("KEY"));
6260         Info_Number = 0x002C;
6261         Info_Mask = 0x20;
6262         break;
6263       case 16: /* Channel Id */
6264         dbug(1,dprintf("CHI"));
6265         Info_Number = 0x0018;
6266         Info_Mask = 0x100;
6267         mixer_set_bchannel_id (plci, Info_Element);
6268         break;
6269       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6270         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6271         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6272         Info_Number = 0x0008;
6273         Info_Mask = 0x01;
6274         if(cause[2] != ie[2]) Info_Element = cause;
6275         break;
6276       case 19: /* Redirected Number */
6277         dbug(1,dprintf("RDN"));
6278         Info_Number = 0x0074;
6279         Info_Mask = 0x400;
6280         break;
6281       case 22: /* Redirecing Number  */
6282         dbug(1,dprintf("RIN"));
6283         Info_Number = 0x0076;
6284         Info_Mask = 0x400;
6285         break;
6286       case 23: /* Notification Indicator  */
6287         dbug(1,dprintf("NI"));
6288         Info_Number = (word)NI;
6289         Info_Mask = 0x210;
6290         break;
6291       case 26: /* Call State  */
6292         dbug(1,dprintf("CST"));
6293         Info_Number = (word)CST;
6294         Info_Mask = 0x01; /* do with cause i.e. for now */
6295         break;
6296       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6297         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6298         Info_Number = 0x8000 |ie[3];
6299         if(iesent) Info_Mask = 0xffff;
6300         else  Info_Mask = 0x10;
6301         Info_Element = "";
6302         break;
6303       default:
6304         Info_Number  = 0;
6305         Info_Mask    = 0;
6306         Info_Element = "";
6307         break;
6308       }
6309     }
6310
6311     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6312     {
6313       for(j=0; j<max_appl; j++)
6314       {
6315         appl = &application[j];
6316         if(Info_Number
6317         && appl->Id
6318         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6319         {
6320           dbug(1,dprintf("NCR_Ind"));
6321           iesent=TRUE;
6322           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6323         }
6324       }
6325     }
6326     else if(!plci->appl)
6327     { /* overlap receiving broadcast */
6328       if(Info_Number==CPN
6329       || Info_Number==KEY
6330       || Info_Number==NI
6331       || Info_Number==DSP
6332       || Info_Number==UUI )
6333       {
6334         for(j=0; j<max_appl; j++)
6335         {
6336           if(test_c_ind_mask_bit (plci, j))
6337           {
6338             dbug(1,dprintf("Ovl_Ind"));
6339             iesent=TRUE;
6340             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6341           }
6342         }
6343       }
6344     }               /* all other signalling states */
6345     else if(Info_Number
6346     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6347     {
6348       dbug(1,dprintf("Std_Ind"));
6349       iesent=TRUE;
6350       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6351     }
6352   }
6353 }
6354
6355
6356 byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse)
6357 {
6358   word i;
6359   word j;
6360   byte   * ie;
6361   word Info_Number;
6362   byte   * Info_Element;
6363   APPL   *appl;
6364   word Info_Mask = 0;
6365   byte iesent=0;
6366
6367   if(
6368       !plci->appl
6369       && !plci->State
6370       && plci->Sig.Ind!=NCR_FACILITY
6371       && !setupParse
6372       )
6373   {
6374     dbug(1,dprintf("NoM-IEParse "));
6375     return 0;
6376   }
6377   dbug(1,dprintf("M-IEParse "));
6378
6379   for(i=0; i<MAX_MULTI_IE; i++)
6380   {
6381     ie = parms[i];
6382     Info_Number = 0;
6383     Info_Element = ie;
6384     if(ie[0])
6385     {
6386       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6387       Info_Number = (word)ie_type;
6388       Info_Mask = (word)info_mask;
6389     }
6390
6391     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6392     {
6393       for(j=0; j<max_appl; j++)
6394       {
6395         appl = &application[j];
6396         if(Info_Number
6397         && appl->Id
6398         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6399         {
6400           iesent = TRUE;
6401           dbug(1,dprintf("Mlt_NCR_Ind"));
6402           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6403         }
6404       }
6405     }
6406     else if(!plci->appl && Info_Number)
6407     {                                        /* overlap receiving broadcast */
6408       for(j=0; j<max_appl; j++)
6409       {
6410         if(test_c_ind_mask_bit (plci, j))
6411         {
6412           iesent = TRUE;
6413           dbug(1,dprintf("Mlt_Ovl_Ind"));
6414           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6415         }
6416       }
6417     }                                        /* all other signalling states */
6418     else if(Info_Number
6419     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6420     {
6421       iesent = TRUE;
6422       dbug(1,dprintf("Mlt_Std_Ind"));
6423       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6424     }
6425   }
6426   return iesent;
6427 }
6428
6429 void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6430 {
6431   word i;
6432    /* Format of multi_ssext_parms[i][]:
6433    0 byte length
6434    1 byte SSEXTIE
6435    2 byte SSEXT_REQ/SSEXT_IND
6436    3 byte length
6437    4 word SSExtCommand
6438    6... Params
6439    */
6440   if(
6441    plci
6442    && plci->State
6443    && plci->Sig.Ind!=NCR_FACILITY
6444     )
6445  for(i=0;i<MAX_MULTI_IE;i++)
6446     {
6447       if(parms[i][0]<6) continue;
6448    if(parms[i][2]==SSEXT_REQ) continue;
6449
6450    if(appl)
6451    {
6452     parms[i][0]=0; /* kill it */
6453     sendf(appl,_MANUFACTURER_I,
6454     Id,
6455     0,
6456     "dwS",
6457     _DI_MANU_ID,
6458     _DI_SSEXT_CTRL,
6459     &parms[i][3]);
6460    }
6461    else if(plci->appl)
6462    {
6463     parms[i][0]=0; /* kill it */
6464     sendf(plci->appl,_MANUFACTURER_I,
6465     Id,
6466     0,
6467     "dwS",
6468     _DI_MANU_ID,
6469     _DI_SSEXT_CTRL,
6470     &parms[i][3]);
6471    }
6472     }
6473 };
6474
6475 void nl_ind(PLCI   * plci)
6476 {
6477   byte ch;
6478   word ncci;
6479   dword Id;
6480   DIVA_CAPI_ADAPTER   * a;
6481   word NCCIcode;
6482   APPL   * APPLptr;
6483   word count;
6484   word Num;
6485   word i, ncpi_state;
6486   byte len, ncci_state;
6487   word msg;
6488   word info = 0;
6489   word fax_feature_bits;
6490   byte fax_send_edata_ack;
6491   static byte v120_header_buffer[2 + 3];
6492   static word fax_info[] = {
6493     0,                     /* T30_SUCCESS                        */
6494     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6495     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6496     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6497     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6498     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6499     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6500     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6501     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6502     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6503     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6504     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6505     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6506     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6507     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6508     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6509     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6510     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6511     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6512     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6513     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6514     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6516     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6517     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6518     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6519     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6520     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6521     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6522     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6523     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6524     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6525     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6526     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6527     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6528     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6529     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6530     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6531     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6532     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6533     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6534     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6535     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6536     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6537     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6538     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6539     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6540   };
6541
6542     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6543
6544
6545   static word rtp_info[] = {
6546     GOOD,                  /* RTP_SUCCESS                       */
6547     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6548   };
6549
6550   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6551   {
6552     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6553     0x00000000, 0x00000000, 0x00000000, 0x00000000
6554   };
6555
6556   ch = plci->NL.IndCh;
6557   a = plci->adapter;
6558   ncci = a->ch_ncci[ch];
6559   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6560   if(plci->tel) Id|=EXT_CONTROLLER;
6561   APPLptr = plci->appl;
6562   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",
6563     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6564
6565   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6566
6567   if (plci->nl_remove_id)
6568   {
6569     plci->NL.RNR = 2; /* discard */
6570     dbug(1,dprintf("NL discard while remove pending"));
6571     return;
6572   }
6573   if((plci->NL.Ind &0x0f)==N_CONNECT)
6574   {
6575     if(plci->State==INC_DIS_PENDING
6576     || plci->State==OUTG_DIS_PENDING
6577     || plci->State==IDLE)
6578     {
6579       plci->NL.RNR = 2; /* discard */
6580       dbug(1,dprintf("discard n_connect"));
6581       return;
6582     }
6583     if(plci->State < INC_ACT_PENDING)
6584     {
6585       plci->NL.RNR = 1; /* flow control */
6586       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6587       return;
6588     }
6589   }
6590
6591   if(!APPLptr)                         /* no application or invalid data */
6592   {                                    /* while reloading the DSP        */
6593     dbug(1,dprintf("discard1"));
6594     plci->NL.RNR = 2;
6595     return;
6596   }
6597
6598   if (((plci->NL.Ind &0x0f) == N_UDATA)
6599      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6600         || (plci->B2_prot == 7)
6601         || (plci->B3_prot == 7)) )
6602   {
6603     plci->ncpi_buffer[0] = 0;
6604
6605     ncpi_state = plci->ncpi_state;
6606     if (plci->NL.complete == 1)
6607     {
6608       byte  * data = &plci->NL.RBuffer->P[0];
6609
6610       if ((plci->NL.RBuffer->length >= 12)
6611         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6612           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6613       {
6614         word conn_opt, ncpi_opt = 0x00;
6615 //      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data);
6616
6617         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6618           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6619         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6620           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6621
6622         data++;    /* indication code */
6623         data += 2; /* timestamp */
6624         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6625           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6626         data++;    /* connected norm */
6627         conn_opt = READ_WORD(data);
6628         data += 2; /* connected options */
6629
6630         WRITE_WORD (&(plci->ncpi_buffer[1]), (word)(READ_DWORD(data) & 0x0000FFFF));
6631
6632         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6633         {
6634           ncpi_opt |= MDM_NCPI_ECM_V42;
6635         }
6636         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6637         {
6638           ncpi_opt |= MDM_NCPI_ECM_MNP;
6639         }
6640         else
6641         {
6642           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6643         }
6644         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6645         {
6646           ncpi_opt |= MDM_NCPI_COMPRESSED;
6647         }
6648         WRITE_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6649         plci->ncpi_buffer[0] = 4;
6650
6651         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6652       }
6653     }
6654     if (plci->B3_prot == 7)
6655     {
6656       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6657        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6658        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6659       {
6660         a->ncci_state[ncci] = INC_ACT_PENDING;
6661         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6662         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6663       }
6664     }
6665
6666     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6667         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6668      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6669      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6670
6671     {
6672       plci->NL.RNR = 2;
6673       return;
6674     }
6675   }
6676
6677   if(plci->NL.complete == 2)
6678     {
6679     if (((plci->NL.Ind &0x0f) == N_UDATA)
6680      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6681     {
6682       switch(plci->RData[0].P[0])
6683       {
6684
6685       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6686         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6687           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6688         break;
6689       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6690         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6691           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6692         break;
6693       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6694         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6695         break;
6696       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6697         dtmf_confirmation (Id, plci);
6698         break;
6699
6700
6701       case UDATA_INDICATION_MIXER_TAP_DATA:
6702         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6703  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6704  if (i != 0)
6705  {
6706    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6707           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6708  }
6709         break;
6710
6711
6712       case UDATA_INDICATION_MIXER_COEFS_SET:
6713         mixer_indication_coefs_set (Id, plci);
6714         break;
6715       case UDATA_INDICATION_XCONNECT_FROM:
6716         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6717         break;
6718       case UDATA_INDICATION_XCONNECT_TO:
6719         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6720         break;
6721
6722
6723       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6724         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6725         break;
6726
6727
6728
6729       default:
6730         break;
6731       }
6732     }
6733     else
6734   {
6735       if ((plci->RData[0].PLength != 0)
6736      && ((plci->B2_prot == B2_V120_ASYNC)
6737       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6738       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6739     {
6740
6741       sendf(plci->appl,_DATA_B3_I,Id,0,
6742             "dwww",
6743             plci->RData[1].P,
6744               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6745             plci->RNum,
6746             plci->RFlags);
6747
6748     }
6749     else
6750     {
6751
6752       sendf(plci->appl,_DATA_B3_I,Id,0,
6753             "dwww",
6754             plci->RData[0].P,
6755             plci->RData[0].PLength,
6756             plci->RNum,
6757             plci->RFlags);
6758
6759     }
6760     }
6761     return;
6762   }
6763
6764   fax_feature_bits = 0;
6765   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6766      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6767      (plci->NL.Ind &0x0f)==N_DISC ||
6768      (plci->NL.Ind &0x0f)==N_EDATA ||
6769      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6770   {
6771     info = 0;
6772     plci->ncpi_buffer[0] = 0;
6773     switch (plci->B3_prot) {
6774     case  0: /*XPARENT*/
6775     case  1: /*T.90 NL*/
6776       break;    /* no network control protocol info - jfr */
6777     case  2: /*ISO8202*/
6778     case  3: /*X25 DCE*/
6779       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6780       plci->ncpi_buffer[0] = (byte)(i+3);
6781       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6782       plci->ncpi_buffer[2] = 0;
6783       plci->ncpi_buffer[3] = 0;
6784       break;
6785     case  4: /*T.30 - FAX*/
6786     case  5: /*T.30 - FAX*/
6787       if(plci->NL.RLength>=sizeof(T30_INFO))
6788       {
6789         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6790         len = 9;
6791         WRITE_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6792         fax_feature_bits = READ_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6793         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6794         if (plci->B3_prot == 5)
6795         {
6796           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6797             i |= 0x8000; /* This is not an ECM connection */
6798           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6799             i |= 0x4000; /* This is a connection with MMR compression */
6800           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6801             i |= 0x2000; /* This is a connection with MR compression */
6802           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6803             i |= 0x0004; /* More documents */
6804           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6805             i |= 0x0002; /* Fax-polling indication */
6806         }
6807         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6808         WRITE_WORD(&(plci->ncpi_buffer[3]),i);
6809         WRITE_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6810         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6811         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6812         plci->ncpi_buffer[len] = 0;
6813         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6814         {
6815           plci->ncpi_buffer[len] = 20;
6816           for (i = 0; i < 20; i++)
6817             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6818         }
6819         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6820         {
6821           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
6822             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6823           else
6824             info = _FAX_PROTOCOL_ERROR;
6825         }
6826
6827         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6828           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6829         {
6830           i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6831           while (i < plci->NL.RBuffer->length)
6832             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6833         }
6834
6835         plci->ncpi_buffer[0] = len;
6836         fax_feature_bits = READ_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6837         WRITE_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6838
6839         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6840  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6841          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6842           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6843          || (((plci->NL.Ind &0x0f) == N_EDATA)
6844           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6845            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6846            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6847  {
6848           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6849  }
6850  if (((plci->NL.Ind &0x0f) == N_DISC)
6851   || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6852   || (((plci->NL.Ind &0x0f) == N_EDATA)
6853    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6854  {
6855           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6856  }
6857       }
6858       break;
6859
6860     case B3_RTP:
6861       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6862       {
6863         if (plci->NL.RLength != 0)
6864         {
6865           info = rtp_info[plci->NL.RBuffer->P[0]];
6866           plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6867           for (i = 1; i < plci->NL.RLength; i++)
6868             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6869         }
6870       }
6871       break;
6872
6873     }
6874     plci->NL.RNR = 2;
6875   }
6876   switch(plci->NL.Ind &0x0f) {
6877   case N_EDATA:
6878     if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6879     {
6880       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6881         ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6882       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6883
6884       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6885        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6886        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6887        && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6888        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6889        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6890       {
6891         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6892         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6893           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6894         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6895  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6896    fax_send_edata_ack = FALSE;
6897       }
6898
6899       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6900       {
6901         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6902         {
6903         case EDATA_T30_DIS:
6904           if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6905            && !(READ_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6906            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6907            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6908           {
6909             a->ncci_state[ncci] = INC_ACT_PENDING;
6910             if (plci->B3_prot == 4)
6911               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6912             else
6913               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6914             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6915           }
6916           break;
6917
6918         case EDATA_T30_TRAIN_OK:
6919           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6920            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6921            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6922           {
6923             if (plci->B3_prot == 4)
6924               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6925             else
6926               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6927             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6928           }
6929           break;
6930
6931         case EDATA_T30_EOP_CAPI:
6932           if (a->ncci_state[ncci] == CONNECTED)
6933           {
6934             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6935             a->ncci_state[ncci] = INC_DIS_PENDING;
6936             plci->ncpi_state = 0;
6937      fax_send_edata_ack = FALSE;
6938           }
6939           break;
6940         }
6941       }
6942       else
6943       {
6944         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6945         {
6946         case EDATA_T30_TRAIN_OK:
6947           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6948            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6949            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6950           {
6951             if (plci->B3_prot == 4)
6952               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6953             else
6954               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6955             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6956           }
6957           break;
6958         }
6959       }
6960       if (fax_send_edata_ack)
6961       {
6962         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6963  plci->fax_edata_ack_length = 1;
6964         start_internal_command (Id, plci, fax_edata_ack_command);
6965       }
6966     }
6967     else
6968     {
6969       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6970     }
6971     break;
6972   case N_CONNECT:
6973     if (!a->ch_ncci[ch])
6974     {
6975       ncci = get_ncci (plci, ch, 0);
6976       Id = (Id & 0xffff) | (((dword) ncci) << 16);
6977     }
6978     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6979       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6980
6981     msg = _CONNECT_B3_I;
6982     if (a->ncci_state[ncci] == IDLE)
6983       plci->channels++;
6984     else if (plci->B3_prot == 1)
6985       msg = _CONNECT_B3_T90_ACTIVE_I;
6986
6987     a->ncci_state[ncci] = INC_CON_PENDING;
6988     if(plci->B3_prot == 4)
6989       sendf(plci->appl,msg,Id,0,"s","");
6990     else
6991       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6992     break;
6993   case N_CONNECT_ACK:
6994     dbug(1,dprintf("N_connect_Ack"));
6995     if (plci->internal_command_queue[0]
6996      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6997       || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6998       || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6999     {
7000       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7001       if (!plci->internal_command)
7002         next_internal_command (Id, plci);
7003       break;
7004     }
7005     msg = _CONNECT_B3_ACTIVE_I;
7006     if (plci->B3_prot == 1)
7007     {
7008       if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7009         msg = _CONNECT_B3_T90_ACTIVE_I;
7010       a->ncci_state[ncci] = INC_ACT_PENDING;
7011       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7012     }
7013     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7014     {
7015       if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7016        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7017        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7018       {
7019         a->ncci_state[ncci] = INC_ACT_PENDING;
7020         if (plci->B3_prot == 4)
7021           sendf(plci->appl,msg,Id,0,"s","");
7022         else
7023           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7024         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7025       }
7026     }
7027     else
7028     {
7029       a->ncci_state[ncci] = INC_ACT_PENDING;
7030       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7031     }
7032     if (plci->adjust_b_restore)
7033     {
7034       plci->adjust_b_restore = FALSE;
7035       start_internal_command (Id, plci, adjust_b_restore);
7036     }
7037     break;
7038   case N_DISC:
7039   case N_DISC_ACK:
7040     if (plci->internal_command_queue[0]
7041      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7042       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7043       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7044     {
7045       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7046       if (!plci->internal_command)
7047         next_internal_command (Id, plci);
7048     }
7049     ncci_state = a->ncci_state[ncci];
7050     ncci_remove (plci, ncci, FALSE);
7051
7052         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7053         /* channel, so we cannot store the state in ncci_state! The */
7054         /* information which channel we received a N_DISC is thus   */
7055         /* stored in the inc_dis_ncci_table buffer.                 */
7056     for(i=0; plci->inc_dis_ncci_table[i]; i++);
7057     plci->inc_dis_ncci_table[i] = (byte) ncci;
7058
7059       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7060     if (!plci->channels
7061      && (plci->B1_resource == 16)
7062      && (plci->State <= CONNECTED))
7063     {
7064       len = 9;
7065       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7066       WRITE_WORD (&plci->ncpi_buffer[1], i);
7067       WRITE_WORD (&plci->ncpi_buffer[3], 0);
7068       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7069       WRITE_WORD (&plci->ncpi_buffer[5], i);
7070       WRITE_WORD (&plci->ncpi_buffer[7], 0);
7071       plci->ncpi_buffer[len] = 0;
7072       plci->ncpi_buffer[0] = len;
7073       if(plci->B3_prot == 4)
7074         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7075       else
7076       {
7077
7078         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7079           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7080         {
7081           plci->ncpi_buffer[++len] = 0;
7082           plci->ncpi_buffer[++len] = 0;
7083           plci->ncpi_buffer[++len] = 0;
7084           plci->ncpi_buffer[0] = len;
7085         }
7086
7087         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7088       }
7089       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7090       plci->ncpi_state = 0;
7091       sig_req(plci,HANGUP,0);
7092       send_req(plci);
7093       plci->State = OUTG_DIS_PENDING;
7094       /* disc here */
7095     }
7096     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7097      && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7098      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7099     {
7100       if (ncci_state == IDLE)
7101       {
7102         if (plci->channels)
7103           plci->channels--;
7104         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7105           if(plci->State == SUSPENDING){
7106             sendf(plci->appl,
7107                   _FACILITY_I,
7108                   Id & 0xffffL,
7109                   0,
7110                   "ws", (word)3, "\x03\x04\x00\x00");
7111             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7112           }
7113           plci_remove(plci);
7114           plci->State=IDLE;
7115         }
7116       }
7117     }
7118     else if (plci->channels)
7119     {
7120       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7121       plci->ncpi_state = 0;
7122       if ((ncci_state == OUTG_REJ_PENDING)
7123        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7124       {
7125         sig_req(plci,HANGUP,0);
7126         send_req(plci);
7127         plci->State = OUTG_DIS_PENDING;
7128       }
7129     }
7130     break;
7131   case N_RESET:
7132     a->ncci_state[ncci] = INC_RES_PENDING;
7133     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7134     break;
7135   case N_RESET_ACK:
7136     a->ncci_state[ncci] = CONNECTED;
7137     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7138     break;
7139
7140   case N_UDATA:
7141     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7142     {
7143       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
7144       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7145       plci->NL.R = plci->RData;
7146       plci->NL.RNum = 1;
7147       return;
7148     }
7149   case N_BDATA:
7150   case N_DATA:
7151     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7152      || (a->ncci_state[ncci] == IDLE)
7153      || (a->ncci_state[ncci] == INC_DIS_PENDING))
7154     {
7155       plci->NL.RNR = 2;
7156       break;
7157     }
7158     if ((a->ncci_state[ncci] != CONNECTED)
7159      && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7160      && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7161     {
7162       dbug(1,dprintf("flow control"));
7163       plci->NL.RNR = 1; /* flow control  */
7164       channel_x_off (plci, ch, 0);
7165       break;
7166     }
7167
7168     NCCIcode = ncci | (((word)a->Id) << 8);
7169
7170                 /* count all buffers within the Application pool    */
7171                 /* belonging to the same NCCI. If this is below the */
7172                 /* number of buffers available per NCCI we accept   */
7173                 /* this packet, otherwise we reject it              */
7174     count = 0;
7175     Num = 0xffff;
7176     for(i=0; i<APPLptr->MaxBuffer; i++) {
7177       if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7178       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7179     }
7180
7181     if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7182     {
7183       dbug(3,dprintf("Flow-Control"));
7184       plci->NL.RNR = 1;
7185       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7186        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7187       {
7188         plci->NL.RNR = 2;
7189         dbug(3,dprintf("DiscardData"));
7190       } else {
7191         channel_x_off (plci, ch, 0);
7192       }
7193       break;
7194     }
7195     else
7196     {
7197       APPLptr->NCCIDataFlowCtrlTimer = 0;
7198     }
7199
7200     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7201     if(!plci->RData[0].P) {
7202       plci->NL.RNR = 1;
7203       channel_x_off (plci, ch, 0);
7204       break;
7205     }
7206
7207     APPLptr->DataNCCI[Num] = NCCIcode;
7208     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7209     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7210
7211     plci->RNum = Num;
7212     plci->RFlags = plci->NL.Ind>>4;
7213     plci->RData[0].PLength = APPLptr->MaxDataLength;
7214     plci->NL.R = plci->RData;
7215     if ((plci->NL.RLength != 0)
7216      && ((plci->B2_prot == B2_V120_ASYNC)
7217       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7218       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7219     {
7220       plci->RData[1].P = plci->RData[0].P;
7221       plci->RData[1].PLength = plci->RData[0].PLength;
7222       plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7223       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7224         plci->RData[0].PLength = 1;
7225       else
7226         plci->RData[0].PLength = 2;
7227       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7228         plci->RFlags |= 0x0010;
7229       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7230         plci->RFlags |= 0x8000;
7231       plci->NL.RNum = 2;
7232     }
7233     else
7234     {
7235       if((plci->NL.Ind &0x0f)==N_UDATA)
7236         plci->RFlags |= 0x0010;
7237
7238       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7239         plci->RFlags |= 0x0001;
7240
7241       plci->NL.RNum = 1;
7242     }
7243     break;
7244   case N_DATA_ACK:
7245     data_ack (plci, ch);
7246     break;
7247   default:
7248     plci->NL.RNR = 2;
7249     break;
7250   }
7251 }
7252
7253 /*------------------------------------------------------------------*/
7254 /* find a free PLCI                                                 */
7255 /*------------------------------------------------------------------*/
7256
7257 word get_plci(DIVA_CAPI_ADAPTER   * a)
7258 {
7259   word i,j;
7260   PLCI   * plci;
7261
7262   dump_plcis (a);
7263   for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7264   if(i==a->max_plci) {
7265     dbug(1,dprintf("get_plci: out of PLCIs"));
7266     return 0;
7267   }
7268   plci = &a->plci[i];
7269   plci->Id = (byte)(i+1);
7270
7271   plci->Sig.Id = 0;
7272   plci->NL.Id = 0;
7273   plci->sig_req = 0;
7274   plci->nl_req = 0;
7275
7276   plci->appl = 0;
7277   plci->relatedPTYPLCI = 0;
7278   plci->State = IDLE;
7279   plci->SuppState = IDLE;
7280   plci->channels = 0;
7281   plci->tel = 0;
7282   plci->B1_resource = 0;
7283   plci->B2_prot = 0;
7284   plci->B3_prot = 0;
7285
7286   plci->command = 0;
7287   plci->m_command = 0;
7288   init_internal_command_queue (plci);
7289   plci->number = 0;
7290   plci->req_in_start = 0;
7291   plci->req_in = 0;
7292   plci->req_out = 0;
7293   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7294   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7295   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7296
7297   plci->data_sent = FALSE;
7298   plci->send_disc = 0;
7299   plci->sig_global_req = 0;
7300   plci->sig_remove_id = 0;
7301   plci->nl_global_req = 0;
7302   plci->nl_remove_id = 0;
7303   plci->adv_nl = 0;
7304   plci->manufacturer = FALSE;
7305   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7306   plci->spoofed_msg = 0;
7307   plci->ptyState = 0;
7308   plci->cr_enquiry = FALSE;
7309   plci->hangup_flow_ctrl_timer = 0;
7310
7311   plci->ncci_ring_list = 0;
7312   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7313   clear_c_ind_mask (plci);
7314   set_group_ind_mask (plci);
7315   plci->fax_connect_info_length = 0;
7316   plci->nsf_control_bits = 0;
7317   plci->ncpi_state = 0x00;
7318   plci->ncpi_buffer[0] = 0;
7319
7320   plci->requested_options_conn = 0;
7321   plci->requested_options = 0;
7322   plci->notifiedcall = 0;
7323   plci->vswitchstate = 0;
7324   plci->vsprot = 0;
7325   plci->vsprotdialect = 0;
7326   init_b1_config (plci);
7327   dbug(1,dprintf("get_plci(%x)",plci->Id));
7328   return i+1;
7329 }
7330
7331 /*------------------------------------------------------------------*/
7332 /* put a parameter in the parameter buffer                          */
7333 /*------------------------------------------------------------------*/
7334
7335 static void add_p(PLCI   * plci, byte code, byte   * p)
7336 {
7337   word p_length;
7338
7339   p_length = 0;
7340   if(p) p_length = p[0];
7341   add_ie(plci, code, p, p_length);
7342 }
7343
7344 /*------------------------------------------------------------------*/
7345 /* put a structure in the parameter buffer                          */
7346 /*------------------------------------------------------------------*/
7347 static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7348 {
7349   if(p) add_ie(plci, code, p->info, (word)p->length);
7350 }
7351
7352 /*------------------------------------------------------------------*/
7353 /* put multiple structures in the parameter buffer                  */
7354 /*------------------------------------------------------------------*/
7355 static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7356 {
7357   byte i;
7358
7359   if(p){
7360     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7361     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7362       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7363       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7364     }
7365   }
7366 }
7367
7368 /*------------------------------------------------------------------*/
7369 /* return the channel number sent by the application in a esc_chi   */
7370 /*------------------------------------------------------------------*/
7371 static byte getChannel(API_PARSE * p)
7372 {
7373   byte i;
7374
7375   if(p){
7376     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7377       if(p->info[i]==2){
7378         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7379       }
7380     }
7381   }
7382   return 0;
7383 }
7384
7385
7386 /*------------------------------------------------------------------*/
7387 /* put an information element in the parameter buffer               */
7388 /*------------------------------------------------------------------*/
7389
7390 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7391 {
7392   word i;
7393
7394   if(!(code &0x80) && !p_length) return;
7395
7396   if(plci->req_in==plci->req_in_start) {
7397     plci->req_in +=2;
7398   }
7399   else {
7400     plci->req_in--;
7401   }
7402   plci->RBuffer[plci->req_in++] = code;
7403
7404   if(p) {
7405     plci->RBuffer[plci->req_in++] = (byte)p_length;
7406     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7407   }
7408
7409   plci->RBuffer[plci->req_in++] = 0;
7410 }
7411
7412 /*------------------------------------------------------------------*/
7413 /* put a unstructured data into the buffer                          */
7414 /*------------------------------------------------------------------*/
7415
7416 void add_d(PLCI   * plci, word length, byte   * p)
7417 {
7418   word i;
7419
7420   if(plci->req_in==plci->req_in_start) {
7421     plci->req_in +=2;
7422   }
7423   else {
7424     plci->req_in--;
7425   }
7426   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7427 }
7428
7429 /*------------------------------------------------------------------*/
7430 /* put parameters from the Additional Info parameter in the         */
7431 /* parameter buffer                                                 */
7432 /*------------------------------------------------------------------*/
7433
7434 void add_ai(PLCI   * plci, API_PARSE * ai)
7435 {
7436   word i;
7437     API_PARSE ai_parms[5];
7438
7439   for(i=0;i<5;i++) ai_parms[i].length = 0;
7440
7441   if(!ai->length)
7442     return;
7443   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7444     return;
7445
7446   add_s (plci,KEY,&ai_parms[1]);
7447   add_s (plci,UUI,&ai_parms[2]);
7448   add_ss(plci,FTY,&ai_parms[3]);
7449 }
7450
7451 /*------------------------------------------------------------------*/
7452 /* put parameter for b1 protocol in the parameter buffer            */
7453 /*------------------------------------------------------------------*/
7454
7455 word add_b1(PLCI   * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7456 {
7457     API_PARSE bp_parms[8];
7458     API_PARSE mdm_cfg[9];
7459     API_PARSE global_config[2];
7460     byte cai[256];
7461   byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7462   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7463   word i;
7464
7465     API_PARSE mdm_cfg_v18[4];
7466   word j, n, w;
7467   dword d;
7468
7469
7470   for(i=0;i<8;i++) bp_parms[i].length = 0;
7471   for(i=0;i<2;i++) global_config[i].length = 0;
7472
7473   dbug(1,dprintf("add_b1"));
7474   api_save_msg(bp, "s", &plci->B_protocol);
7475
7476   if(b_channel_info==2){
7477     plci->B1_resource = 0;
7478     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7479     add_p(plci, CAI, "\x01\x00");
7480     dbug(1,dprintf("Cai=1,0 (no resource)"));
7481     return 0;
7482   }
7483
7484   if(plci->tel == CODEC_PERMANENT) return 0;
7485   else if(plci->tel == CODEC){
7486     plci->B1_resource = 1;
7487     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7488     add_p(plci, CAI, "\x01\x01");
7489     dbug(1,dprintf("Cai=1,1 (Codec)"));
7490     return 0;
7491   }
7492   else if(plci->tel == ADV_VOICE){
7493     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7494     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7495     voice_cai[1] = plci->B1_resource;
7496     WRITE_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7497     add_p(plci, CAI, voice_cai);
7498     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7499     return 0;
7500   }
7501   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7502   if (plci->call_dir & CALL_DIR_OUT)
7503     plci->call_dir |= CALL_DIR_ORIGINATE;
7504   else if (plci->call_dir & CALL_DIR_IN)
7505     plci->call_dir |= CALL_DIR_ANSWER;
7506
7507   if(!bp->length){
7508     plci->B1_resource = 0x5;
7509     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7510     add_p(plci, CAI, "\x01\x05");
7511     return 0;
7512   }
7513
7514   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7515   if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7516   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7517   {
7518     bp_parms[6].length = 0;
7519     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7520     {
7521       dbug(1,dprintf("b-form.!"));
7522       return _WRONG_MESSAGE_FORMAT;
7523     }
7524   }
7525   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7526   {
7527     dbug(1,dprintf("b-form.!"));
7528     return _WRONG_MESSAGE_FORMAT;
7529   }
7530
7531   if(bp_parms[6].length)
7532   {
7533     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7534     {
7535       return _WRONG_MESSAGE_FORMAT;
7536     }
7537     switch(READ_WORD(global_config[0].info))
7538     {
7539     case 1:
7540       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7541       break;
7542     case 2:
7543       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7544       break;
7545     }
7546   }
7547   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7548
7549
7550   if ((READ_WORD(bp_parms[0].info) == B1_RTP)
7551    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7552   {
7553     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7554     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7555     cai[1] = plci->B1_resource;
7556     cai[2] = 0;
7557     cai[3] = 0;
7558     cai[4] = 0;
7559     WRITE_WORD(&cai[5],plci->appl->MaxDataLength);
7560     for (i = 0; i < bp_parms[3].length; i++)
7561       cai[7+i] = bp_parms[3].info[1+i];
7562     cai[0] = 6 + bp_parms[3].length;
7563     add_p(plci, CAI, cai);
7564     return 0;
7565   }
7566
7567
7568   if ((READ_WORD(bp_parms[0].info) == B1_PIAFS)
7569    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7570   {
7571     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7572     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7573     cai[1] = plci->B1_resource;
7574     cai[2] = 0;
7575     cai[3] = 0;
7576     cai[4] = 0;
7577     WRITE_WORD(&cai[5],plci->appl->MaxDataLength);
7578     cai[0] = 6;
7579     add_p(plci, CAI, cai);
7580     return 0;
7581   }
7582
7583
7584   if ((READ_WORD(bp_parms[0].info) >= 32)
7585    || (!((1L << READ_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7586     && ((READ_WORD(bp_parms[0].info) != 3)
7587      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7588      || ((bp_parms[3].length != 0) && (READ_WORD(&bp_parms[3].info[1]) != 0) && (READ_WORD(&bp_parms[3].info[1]) != 56000)))))
7589   {
7590     return _B1_NOT_SUPPORTED;
7591   }
7592   plci->B1_resource = add_b1_facilities (plci, resource[READ_WORD(bp_parms[0].info)],
7593     (word)(b1_facilities & ~B1_FACILITY_VOICE));
7594   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7595   cai[0] = 6;
7596   cai[1] = plci->B1_resource;
7597   for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7598
7599   if ((READ_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7600    || (READ_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7601    || (READ_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7602   { /* B1 - modem */
7603     for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7604
7605     if (bp_parms[3].length)
7606     {
7607       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7608       {
7609         return (_WRONG_MESSAGE_FORMAT);
7610       }
7611         
7612       cai[2] = 0; /* Bit rate for adaptation */
7613
7614       dbug(1,dprintf("MDM Max Bit Rate:<%d>", READ_WORD(mdm_cfg[0].info)));
7615
7616       WRITE_WORD (&cai[13], 0);                          /* Min Tx speed */
7617       WRITE_WORD (&cai[15], READ_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7618       WRITE_WORD (&cai[17], 0);                          /* Min Rx speed */
7619       WRITE_WORD (&cai[19], READ_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7620
7621       cai[3] = 0; /* Async framing parameters */
7622       switch (READ_WORD (mdm_cfg[2].info))
7623       {       /* Parity     */
7624       case 1: /* odd parity */
7625         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7626         dbug(1,dprintf("MDM: odd parity"));
7627         break;
7628
7629       case 2: /* even parity */
7630         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7631         dbug(1,dprintf("MDM: even parity"));
7632         break;
7633
7634       default:
7635         dbug(1,dprintf("MDM: no parity"));
7636         break;
7637       }
7638
7639       switch (READ_WORD (mdm_cfg[3].info))
7640       {       /* stop bits   */
7641       case 1: /* 2 stop bits */
7642         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7643         dbug(1,dprintf("MDM: 2 stop bits"));
7644         break;
7645
7646       default:
7647         dbug(1,dprintf("MDM: 1 stop bit"));
7648         break;
7649       }
7650
7651       switch (READ_WORD (mdm_cfg[1].info))
7652       {     /* char length */
7653       case 5:
7654         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7655         dbug(1,dprintf("MDM: 5 bits"));
7656         break;
7657
7658       case 6:
7659         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7660         dbug(1,dprintf("MDM: 6 bits"));
7661         break;
7662
7663       case 7:
7664         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7665         dbug(1,dprintf("MDM: 7 bits"));
7666         break;
7667
7668       default:
7669         dbug(1,dprintf("MDM: 8 bits"));
7670         break;
7671       }
7672
7673       cai[7] = 0; /* Line taking options */
7674       cai[8] = 0; /* Modulation negotiation options */
7675       cai[9] = 0; /* Modulation options */
7676
7677       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7678       {
7679         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7680         dbug(1, dprintf("MDM: Reverse direction"));
7681       }
7682
7683       if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7684       {
7685         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7686         dbug(1, dprintf("MDM: Disable retrain"));
7687       }
7688
7689       if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7690       {
7691         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7692         dbug(1, dprintf("MDM: Disable ring tone"));
7693       }
7694
7695       if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7696       {
7697         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7698         dbug(1, dprintf("MDM: 1800 guard tone"));
7699       }
7700       else if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7701       {
7702         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7703         dbug(1, dprintf("MDM: 550 guard tone"));
7704       }
7705
7706       if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7707       {
7708         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7709         dbug(1, dprintf("MDM: V100"));
7710       }
7711       else if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7712       {
7713         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7714         dbug(1, dprintf("MDM: IN CLASS"));
7715       }
7716       else if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7717       {
7718         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7719         dbug(1, dprintf("MDM: DISABLED"));
7720       }
7721       cai[0] = 20;
7722
7723       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7724        && (READ_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7725       {
7726         plci->requested_options |= 1L << PRIVATE_V18;
7727       }
7728       if (READ_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7729         plci->requested_options |= 1L << PRIVATE_VOWN;
7730
7731       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7732         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7733       {
7734         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7735         {
7736           i = 27;
7737           if (mdm_cfg[6].length >= 4)
7738           {
7739             d = READ_DWORD(&mdm_cfg[6].info[1]);
7740             cai[7] |= (byte) d;          /* line taking options */
7741             cai[9] |= (byte)(d >> 8);    /* modulation options */
7742             cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7743             cai[++i] = (byte)(d >> 24);
7744             if (mdm_cfg[6].length >= 8)
7745             {
7746               d = READ_DWORD(&mdm_cfg[6].info[5]);
7747               cai[10] |= (byte) d;        /* disabled modulations mask */
7748               cai[11] |= (byte)(d >> 8);
7749               if (mdm_cfg[6].length >= 12)
7750               {
7751                 d = READ_DWORD(&mdm_cfg[6].info[9]);
7752                 cai[12] = (byte) d;          /* enabled modulations mask */
7753                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7754                 cai[++i] = (byte)(d >> 16);
7755                 cai[++i] = (byte)(d >> 24);
7756                 cai[++i] = 0;
7757                 if (mdm_cfg[6].length >= 14)
7758                 {
7759                   w = READ_WORD(&mdm_cfg[6].info[13]);
7760                   if (w != 0)
7761                     WRITE_WORD(&cai[13], w);  /* min tx speed */
7762                   if (mdm_cfg[6].length >= 16)
7763                   {
7764                     w = READ_WORD(&mdm_cfg[6].info[15]);
7765                     if (w != 0)
7766                       WRITE_WORD(&cai[15], w);  /* max tx speed */
7767                     if (mdm_cfg[6].length >= 18)
7768                     {
7769                       w = READ_WORD(&mdm_cfg[6].info[17]);
7770                       if (w != 0)
7771                         WRITE_WORD(&cai[17], w);  /* min rx speed */
7772                       if (mdm_cfg[6].length >= 20)
7773                       {
7774                         w = READ_WORD(&mdm_cfg[6].info[19]);
7775                         if (w != 0)
7776                           WRITE_WORD(&cai[19], w);  /* max rx speed */
7777                         if (mdm_cfg[6].length >= 22)
7778                         {
7779                           w = READ_WORD(&mdm_cfg[6].info[21]);
7780                           cai[23] = (byte)(-((short) w));  /* transmit level */
7781                           if (mdm_cfg[6].length >= 24)
7782                           {
7783                             w = READ_WORD(&mdm_cfg[6].info[23]);
7784                             cai[22] |= (byte) w;        /* info options mask */
7785                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7786                           }
7787                         }
7788                       }
7789                     }
7790                   }
7791                 }
7792               }
7793             }
7794           }
7795           cai[27] = i - 27;
7796           i++;
7797           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7798           {
7799             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7800             {
7801               for (n = 0; n < 3; n++)
7802               {
7803                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7804                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7805                   cai[i+j] = mdm_cfg_v18[n].info[j];
7806                 i += cai[i] + 1;
7807               }
7808             }
7809           }
7810           cai[0] = (byte)(i - 1);
7811         }
7812       }
7813
7814     }
7815   }
7816   if(READ_WORD(bp_parms[0].info)==2 ||                         // V.110 async
7817      READ_WORD(bp_parms[0].info)==3 )                          // V.110 sync
7818   {
7819     if(bp_parms[3].length){
7820       dbug(1,dprintf("V.110,%d",READ_WORD(&bp_parms[3].info[1])));
7821       switch(READ_WORD(&bp_parms[3].info[1])){                 // Rate
7822         case 0:
7823         case 56000:
7824           if(READ_WORD(bp_parms[0].info)==3){                  //V.110 sync 56k
7825             dbug(1,dprintf("56k sync HSCX"));
7826             cai[1] = 8;
7827             cai[2] = 0;
7828             cai[3] = 0;
7829           }
7830           else if(READ_WORD(bp_parms[0].info)==2){
7831             dbug(1,dprintf("56k async DSP"));
7832             cai[2] = 9;
7833           }
7834           break;
7835         case 50:     cai[2] = 1;  break;
7836         case 75:     cai[2] = 1;  break;
7837         case 110:    cai[2] = 1;  break;
7838         case 150:    cai[2] = 1;  break;
7839         case 200:    cai[2] = 1;  break;
7840         case 300:    cai[2] = 1;  break;
7841         case 600:    cai[2] = 1;  break;
7842         case 1200:   cai[2] = 2;  break;
7843         case 2400:   cai[2] = 3;  break;
7844         case 4800:   cai[2] = 4;  break;
7845         case 7200:   cai[2] = 10; break;
7846         case 9600:   cai[2] = 5;  break;
7847         case 12000:  cai[2] = 13; break;
7848         case 24000:  cai[2] = 0;  break;
7849         case 14400:  cai[2] = 11; break;
7850         case 19200:  cai[2] = 6;  break;
7851         case 28800:  cai[2] = 12; break;
7852         case 38400:  cai[2] = 7;  break;
7853         case 48000:  cai[2] = 8;  break;
7854         case 76:     cai[2] = 15; break;  /* 75/1200     */
7855         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7856         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7857
7858         default:
7859           return _B1_PARM_NOT_SUPPORTED;
7860       }
7861       cai[3] = 0;
7862       if (cai[1] == 13)                                        // v.110 async
7863       {
7864         if (bp_parms[3].length >= 8)
7865         {
7866           switch (READ_WORD (&bp_parms[3].info[3]))
7867           {       /* char length */
7868           case 5:
7869             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7870             break;
7871           case 6:
7872             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7873             break;
7874           case 7:
7875             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7876             break;
7877           }
7878           switch (READ_WORD (&bp_parms[3].info[5]))
7879           {       /* Parity     */
7880           case 1: /* odd parity */
7881             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7882             break;
7883           case 2: /* even parity */
7884             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7885             break;
7886           }
7887           switch (READ_WORD (&bp_parms[3].info[7]))
7888           {       /* stop bits   */
7889           case 1: /* 2 stop bits */
7890             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7891             break;
7892           }
7893         }
7894       }
7895     }
7896     else if(cai[1]==8 || READ_WORD(bp_parms[0].info)==3 ){
7897       dbug(1,dprintf("V.110 default 56k sync"));
7898       cai[1] = 8;
7899       cai[2] = 0;
7900       cai[3] = 0;
7901     }
7902     else {
7903       dbug(1,dprintf("V.110 default 9600 async"));
7904       cai[2] = 5;
7905     }
7906   }
7907   WRITE_WORD(&cai[5],plci->appl->MaxDataLength);
7908   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]));
7909 //HexDump ("CAI", sizeof(cai), &cai[0]);
7910
7911   add_p(plci, CAI, cai);
7912   return 0;
7913 }
7914
7915 /*------------------------------------------------------------------*/
7916 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7917 /*------------------------------------------------------------------*/
7918
7919 word add_b23(PLCI   * plci, API_PARSE * bp)
7920 {
7921   word i, fax_control_bits;
7922   byte pos, len;
7923   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7924     API_PARSE bp_parms[8];
7925   API_PARSE * b1_config;
7926   API_PARSE * b2_config;
7927     API_PARSE b2_config_parms[8];
7928   API_PARSE * b3_config;
7929     API_PARSE b3_config_parms[6];
7930     API_PARSE global_config[2];
7931
7932   static byte llc[3] = {2,0,0};
7933   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7934   static byte nlc[256];
7935   static byte lli[12] = {1,1};
7936
7937   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7938   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7939
7940   const byte llc3[] = {4,3,2,2,6,6,0};
7941   const byte header[] = {0,2,3,3,0,0,0};
7942
7943   for(i=0;i<8;i++) bp_parms[i].length = 0;
7944   for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7945   for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7946
7947   lli[0] = 1;
7948   lli[1] = 1;
7949   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7950     lli[1] |= 2;
7951   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7952     lli[1] |= 4;
7953
7954   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7955     lli[1] |= 0x10;
7956     if (plci->rx_dma_descriptor <= 0) {
7957       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7958       if (plci->rx_dma_descriptor >= 0)
7959         plci->rx_dma_descriptor++;
7960     }
7961     if (plci->rx_dma_descriptor > 0) {
7962       lli[0] = 6;
7963       lli[1] |= 0x40;
7964       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7965       lli[3] = (byte)plci->rx_dma_magic;
7966       lli[4] = (byte)(plci->rx_dma_magic >>  8);
7967       lli[5] = (byte)(plci->rx_dma_magic >> 16);
7968       lli[6] = (byte)(plci->rx_dma_magic >> 24);
7969     }
7970   }
7971
7972   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7973     lli[1] |= 0x20;
7974   }
7975
7976   dbug(1,dprintf("add_b23"));
7977   api_save_msg(bp, "s", &plci->B_protocol);
7978
7979   if(!bp->length && plci->tel)
7980   {
7981     plci->adv_nl = TRUE;
7982     dbug(1,dprintf("Default adv.Nl"));
7983     add_p(plci,LLI,lli);
7984     plci->B2_prot = 1 /*XPARENT*/;
7985     plci->B3_prot = 0 /*XPARENT*/;
7986     llc[1] = 2;
7987     llc[2] = 4;
7988     add_p(plci, LLC, llc);
7989     dlc[0] = 2;
7990     WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
7991     add_p(plci, DLC, dlc);
7992     return 0;
7993   }
7994
7995   if(!bp->length) /*default*/
7996   {   
7997     dbug(1,dprintf("ret default"));
7998     add_p(plci,LLI,lli);
7999     plci->B2_prot = 0 /*X.75   */;
8000     plci->B3_prot = 0 /*XPARENT*/;
8001     llc[1] = 1;
8002     llc[2] = 4;
8003     add_p(plci, LLC, llc);
8004     dlc[0] = 2;
8005     WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
8006     add_p(plci, DLC, dlc);
8007     return 0;
8008   }
8009   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8010   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8011
8012   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8013   {
8014     bp_parms[6].length = 0;
8015     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8016     {
8017       dbug(1,dprintf("b-form.!"));
8018       return _WRONG_MESSAGE_FORMAT;
8019     }
8020   }
8021   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8022   {
8023     dbug(1,dprintf("b-form.!"));
8024     return _WRONG_MESSAGE_FORMAT;
8025   }
8026
8027   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8028   {  
8029     if(READ_WORD(bp_parms[1].info)!=1
8030     || READ_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8031     plci->adv_nl = TRUE;
8032   }
8033   else if(plci->tel) return _B2_NOT_SUPPORTED;
8034
8035
8036   if ((READ_WORD(bp_parms[1].info) == B2_RTP)
8037    && (READ_WORD(bp_parms[2].info) == B3_RTP)
8038    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8039   {
8040     add_p(plci,LLI,lli);
8041     plci->B2_prot = (byte) READ_WORD(bp_parms[1].info);
8042     plci->B3_prot = (byte) READ_WORD(bp_parms[2].info);
8043     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8044     llc[2] = 4;
8045     add_p(plci, LLC, llc);
8046     dlc[0] = 2;
8047     WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
8048     dlc[3] = 3; /* Addr A */
8049     dlc[4] = 1; /* Addr B */
8050     dlc[5] = 7; /* modulo mode */
8051     dlc[6] = 7; /* window size */
8052     dlc[7] = 0; /* XID len Lo  */
8053     dlc[8] = 0; /* XID len Hi  */
8054     for (i = 0; i < bp_parms[4].length; i++)
8055       dlc[9+i] = bp_parms[4].info[1+i];
8056     dlc[0] = (byte)(8 + bp_parms[4].length);
8057     add_p(plci, DLC, dlc);
8058     for (i = 0; i < bp_parms[5].length; i++)
8059       nlc[1+i] = bp_parms[5].info[1+i];
8060     nlc[0] = (byte)(bp_parms[5].length);
8061     add_p(plci, NLC, nlc);
8062     return 0;
8063   }
8064
8065
8066
8067   if ((READ_WORD(bp_parms[1].info) >= 32)
8068    || (!((1L << READ_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8069     && ((READ_WORD(bp_parms[1].info) != B2_PIAFS)
8070      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8071
8072   {
8073     return _B2_NOT_SUPPORTED;
8074   }
8075   if ((READ_WORD(bp_parms[2].info) >= 32)
8076    || !((1L << READ_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8077   {
8078     return _B3_NOT_SUPPORTED;
8079   }
8080   if ((READ_WORD(bp_parms[1].info) != B2_SDLC)
8081    && ((READ_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8082     || (READ_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8083     || (READ_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8084   {
8085     return (add_modem_b23 (plci, bp_parms));
8086   }
8087
8088   add_p(plci,LLI,lli);
8089
8090   plci->B2_prot = (byte) READ_WORD(bp_parms[1].info);
8091   plci->B3_prot = (byte) READ_WORD(bp_parms[2].info);
8092   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8093
8094   if(bp_parms[6].length)
8095   {
8096     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8097     {
8098       return _WRONG_MESSAGE_FORMAT;
8099     }
8100     switch(READ_WORD(global_config[0].info))
8101     {
8102     case 1:
8103       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8104       break;
8105     case 2:
8106       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8107       break;
8108     }
8109   }
8110   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8111
8112
8113   if (plci->B2_prot == B2_PIAFS)
8114     llc[1] = PIAFS_CRC;
8115   else
8116 /* IMPLEMENT_PIAFS */
8117   {
8118     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8119              llc2_out[READ_WORD(bp_parms[1].info)] : llc2_in[READ_WORD(bp_parms[1].info)];
8120   }
8121   llc[2] = llc3[READ_WORD(bp_parms[2].info)];
8122
8123   add_p(plci, LLC, llc);
8124
8125   dlc[0] = 2;
8126   WRITE_WORD(&dlc[1], plci->appl->MaxDataLength +
8127                       header[READ_WORD(bp_parms[2].info)]);
8128
8129   b1_config = &bp_parms[3];
8130   nlc[0] = 0;
8131   if(plci->B3_prot == 4
8132   || plci->B3_prot == 5)
8133   {
8134     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8135     nlc[0] = sizeof(T30_INFO);
8136     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8137       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8138     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8139     if(b1_config->length>=2)
8140     {
8141       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(READ_WORD(&b1_config->info[1])/2400);
8142     }
8143   }
8144   b2_config = &bp_parms[4];
8145
8146
8147   if (llc[1] == PIAFS_CRC)
8148   {
8149     if (plci->B3_prot != B3_TRANSPARENT)
8150     {
8151       return _B_STACK_NOT_SUPPORTED;
8152     }
8153     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8154       return _WRONG_MESSAGE_FORMAT;
8155     }
8156     WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
8157     dlc[3] = 0; /* Addr A */
8158     dlc[4] = 0; /* Addr B */
8159     dlc[5] = 0; /* modulo mode */
8160     dlc[6] = 0; /* window size */
8161     if (b2_config->length >= 7){
8162       dlc[ 7] = 7; 
8163       dlc[ 8] = 0; 
8164       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8165       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8166       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8167       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8168       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8169       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8170       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8171       dlc[ 0] = 15;
8172       if(b2_config->length >= 8) { /* PIAFS control abilities */
8173         dlc[ 7] = 10; 
8174         dlc[16] = 2; /* Length of PIAFS extention */
8175         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8176         dlc[18] = b2_config_parms[4].info[0]; /* value */
8177         dlc[ 0] = 18;
8178       }
8179     }
8180     else /* default values, 64K, variable, no compression */
8181     {
8182       dlc[ 7] = 7; 
8183       dlc[ 8] = 0; 
8184       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8185       dlc[10] = 0x03; /* V.42bis P0 */
8186       dlc[11] = 0;    /* V.42bis P0 */
8187       dlc[12] = 0;    /* V.42bis P1 */
8188       dlc[13] = 0;    /* V.42bis P1 */
8189       dlc[14] = 0;    /* V.42bis P2 */
8190       dlc[15] = 0;    /* V.42bis P2 */
8191     dlc[ 0] = 15;
8192     }
8193     add_p(plci, DLC, dlc);
8194   }
8195   else
8196
8197   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8198   {
8199     if (plci->B3_prot != B3_TRANSPARENT)
8200       return _B_STACK_NOT_SUPPORTED;
8201
8202     dlc[0] = 6;
8203     WRITE_WORD (&dlc[1], READ_WORD (&dlc[1]) + 2);
8204     dlc[3] = 0x08;
8205     dlc[4] = 0x01;
8206     dlc[5] = 127;
8207     dlc[6] = 7;
8208     if (b2_config->length != 0)
8209     {
8210       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8211         return _WRONG_MESSAGE_FORMAT;
8212       }
8213       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8214       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8215       if (b2_config->info[3] != 128)
8216       {
8217         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8218         return _B2_PARM_NOT_SUPPORTED;
8219       }
8220       dlc[5] = (byte)(b2_config->info[3] - 1);
8221       dlc[6] = b2_config->info[4];
8222       if(llc[1]==V120_V42BIS){
8223         if (b2_config->length >= 10){
8224           dlc[ 7] = 6; 
8225           dlc[ 8] = 0; 
8226           dlc[ 9] = b2_config_parms[4].info[0];
8227           dlc[10] = b2_config_parms[4].info[1];
8228           dlc[11] = b2_config_parms[5].info[0];
8229           dlc[12] = b2_config_parms[5].info[1];
8230           dlc[13] = b2_config_parms[6].info[0];
8231           dlc[14] = b2_config_parms[6].info[1];
8232           dlc[ 0] = 14;
8233           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8234           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8235           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8236         }
8237         else {
8238           dlc[ 6] = 14;
8239         }
8240       }
8241     }
8242   }
8243   else
8244   {
8245     if(b2_config->length)
8246     {
8247       dbug(1,dprintf("B2-Config"));
8248       if(llc[1]==X75_V42BIS){
8249         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8250         {
8251           return _WRONG_MESSAGE_FORMAT;
8252         }
8253       }
8254       else {
8255         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8256         {
8257           return _WRONG_MESSAGE_FORMAT;
8258         }
8259       }
8260           /* if B2 Protocol is LAPD, b2_config structure is different */
8261       if(llc[1]==6)
8262       {
8263         dlc[0] = 4;
8264         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8265         else dlc[2] = 0x01;
8266         if( (b2_config->length>=2) && (plci->B2_prot==12) )
8267         {
8268           SAPI = b2_config->info[2];    /* SAPI */
8269         }
8270         dlc[1] = SAPI;
8271         if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8272         {
8273           dlc[3] = 127;      /* Mode */
8274         }
8275         else
8276         {
8277           dlc[3] = 7;        /* Mode */
8278         }
8279    
8280         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8281         else dlc[4] = 1;
8282         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8283         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8284       }
8285       else
8286       {
8287         dlc[0] = (byte)(b2_config_parms[4].length+6);
8288         dlc[3] = b2_config->info[1];
8289         dlc[4] = b2_config->info[2];
8290         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8291           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8292           return _B2_PARM_NOT_SUPPORTED;
8293         }
8294
8295         dlc[5] = (byte)(b2_config->info[3]-1);
8296         dlc[6] = b2_config->info[4];
8297         if(dlc[6]>dlc[5]){
8298           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]));
8299           return _B2_PARM_NOT_SUPPORTED;
8300         }
8301  
8302         if(llc[1]==X75_V42BIS) {
8303           if (b2_config->length >= 10){
8304             dlc[ 7] = 6; 
8305             dlc[ 8] = 0; 
8306             dlc[ 9] = b2_config_parms[4].info[0];
8307             dlc[10] = b2_config_parms[4].info[1];
8308             dlc[11] = b2_config_parms[5].info[0];
8309             dlc[12] = b2_config_parms[5].info[1];
8310             dlc[13] = b2_config_parms[6].info[0];
8311             dlc[14] = b2_config_parms[6].info[1];
8312             dlc[ 0] = 14;
8313             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8314             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8315             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8316           }
8317           else {
8318             dlc[ 6] = 14;
8319           }
8320
8321         }
8322         else {
8323           WRITE_WORD(&dlc[7], (word)b2_config_parms[4].length);
8324           for(i=0; i<b2_config_parms[4].length; i++)
8325             dlc[11+i] = b2_config_parms[4].info[1+i];
8326         }
8327       }
8328     }
8329   }
8330   add_p(plci, DLC, dlc);
8331
8332   b3_config = &bp_parms[5];
8333   if(b3_config->length)
8334   {
8335     if(plci->B3_prot == 4 
8336     || plci->B3_prot == 5)
8337     {
8338       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8339       {
8340         return _WRONG_MESSAGE_FORMAT;
8341       }
8342       i = READ_WORD((byte   *)(b3_config_parms[0].info));
8343       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8344         ((plci->B3_prot == 4) && (((byte)(READ_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8345       ((T30_INFO *)&nlc[1])->data_format = (byte)(READ_WORD((byte   *)b3_config_parms[1].info));
8346       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8347       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8348         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8349       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8350       {
8351
8352         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8353           & (1L << PRIVATE_FAX_PAPER_FORMATS))
8354         {
8355           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8356             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8357             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8358         }
8359
8360  ((T30_INFO *)&nlc[1])->recording_properties =
8361    T30_RECORDING_WIDTH_ISO_A3 |
8362    (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8363    (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8364       }
8365       if(plci->B3_prot == 5)
8366       {
8367         if (i & 0x0002) /* Accept incoming fax-polling requests */
8368           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8369         if (i & 0x2000) /* Do not use MR compression */
8370           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8371         if (i & 0x4000) /* Do not use MMR compression */
8372           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8373         if (i & 0x8000) /* Do not use ECM */
8374           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8375         if (plci->fax_connect_info_length != 0)
8376         {
8377           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8378           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8379           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8380           fax_control_bits |= READ_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8381             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8382         }
8383       }
8384       /* copy station id to NLC */
8385       for(i=0; i<20; i++)
8386       {
8387         if(i<b3_config_parms[2].length)
8388         {
8389           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8390         }
8391         else
8392         {
8393           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8394         }
8395       }
8396       ((T30_INFO *)&nlc[1])->station_id_len = 20;
8397       /* copy head line to NLC */
8398       if(b3_config_parms[3].length)
8399       {
8400
8401         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8402         if (pos != 0)
8403         {
8404           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8405             pos = 0;
8406           else
8407           {
8408             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8409             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8410             len = (byte)b3_config_parms[2].length;
8411             if (len > 20)
8412               len = 20;
8413             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8414             {
8415               for (i = 0; i < len; i++)
8416                 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8417               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8418               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8419             }
8420           }
8421         }
8422
8423         len = (byte)b3_config_parms[3].length;
8424         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8425           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8426         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8427         nlc[0] += (byte)(pos + len);
8428         for (i = 0; i < len; i++)
8429           ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
8430         }
8431       else
8432         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8433
8434       plci->nsf_control_bits = 0;
8435       if(plci->B3_prot == 5)
8436       {
8437         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8438          && (READ_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8439         {
8440           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8441         }
8442         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8443          && (READ_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8444         {
8445           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8446         }
8447         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8448           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8449         {
8450         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8451           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8452         {
8453           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8454           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8455             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8456           }
8457             len = nlc[0];
8458           pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8459    if (pos < plci->fax_connect_info_length)
8460    {
8461      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8462               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8463           }
8464    else
8465      nlc[++len] = 0;
8466    if (pos < plci->fax_connect_info_length)
8467    {
8468      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8469               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8470           }
8471    else
8472      nlc[++len] = 0;
8473           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8474             & (1L << PRIVATE_FAX_NONSTANDARD))
8475           {
8476      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8477      {
8478               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8479                 plci->nsf_control_bits = READ_WORD(&plci->fax_connect_info_buffer[pos+2]);
8480        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8481                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8482             }
8483      else
8484      {
8485               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8486               {
8487                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8488                 nlc[++len] = 0;
8489               }
8490        else
8491        {
8492                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8493                   plci->nsf_control_bits = READ_WORD(&b3_config_parms[4].info[2]);
8494          nlc[++len] = (byte)(b3_config_parms[4].length);
8495          for (i = 0; i < b3_config_parms[4].length; i++)
8496     nlc[++len] = b3_config_parms[4].info[1+i];
8497        }
8498             }
8499           }
8500             nlc[0] = len;
8501    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8502     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8503    {
8504             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8505           }
8506         }
8507       }
8508
8509       WRITE_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8510       len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8511       for (i = 0; i < len; i++)
8512         plci->fax_connect_info_buffer[i] = nlc[1+i];
8513       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8514       i += ((T30_INFO *)&nlc[1])->head_line_len;
8515       while (i < nlc[0])
8516         plci->fax_connect_info_buffer[len++] = nlc[++i];
8517       plci->fax_connect_info_length = len;
8518     }
8519     else
8520     {
8521       nlc[0] = 14;
8522       if(b3_config->length!=16)
8523         return _B3_PARM_NOT_SUPPORTED;
8524       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8525       if(READ_WORD(&b3_config->info[13])!=8 && READ_WORD(&b3_config->info[13])!=128)
8526         return _B3_PARM_NOT_SUPPORTED;
8527       nlc[13] = b3_config->info[13];
8528       if(READ_WORD(&b3_config->info[15])>=nlc[13])
8529         return _B3_PARM_NOT_SUPPORTED;
8530       nlc[14] = b3_config->info[15];
8531     }
8532   }
8533   else
8534   {
8535     if (plci->B3_prot == 4 
8536      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8537   }
8538   add_p(plci, NLC, nlc);
8539   return 0;
8540 }
8541
8542 /*----------------------------------------------------------------*/
8543 /*      make the same as add_b23, but only for the modem related  */
8544 /*      L2 and L3 B-Chan protocol.                                */
8545 /*                                                                */
8546 /*      Enabled L2 and L3 Configurations:                         */
8547 /*        If L1 == Modem all negotiation                          */
8548 /*          only L2 == Modem with full negotiation is allowed     */
8549 /*        If L1 == Modem async or sync                            */
8550 /*          only L2 == Transparent is allowed                     */
8551 /*        L3 == Modem or L3 == Transparent are allowed            */
8552 /*      B2 Configuration for modem:                               */
8553 /*          word : enable/disable compression, bitoptions         */
8554 /*      B3 Configuration for modem:                               */
8555 /*          empty                                                 */
8556 /*----------------------------------------------------------------*/
8557 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8558 {
8559   static byte lli[12] = {1,1};
8560   static byte llc[3] = {2,0,0};
8561   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8562     API_PARSE mdm_config[2];
8563   word i;
8564   word b2_config = 0;
8565
8566   for(i=0;i<2;i++) mdm_config[i].length = 0;
8567   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8568
8569   if (((READ_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8570     && (READ_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8571    || ((READ_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8572     && (READ_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8573   {
8574     return (_B_STACK_NOT_SUPPORTED);
8575   }
8576   if ((READ_WORD(bp_parms[2].info) != B3_MODEM)
8577    && (READ_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8578   {
8579     return (_B_STACK_NOT_SUPPORTED);
8580   }
8581
8582   plci->B2_prot = (byte) READ_WORD(bp_parms[1].info);
8583   plci->B3_prot = (byte) READ_WORD(bp_parms[2].info);
8584
8585   if ((READ_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8586   {
8587     if (api_parse (&bp_parms[4].info[1],
8588                   (word)bp_parms[4].length, "w",
8589                   mdm_config))
8590     {
8591       return (_WRONG_MESSAGE_FORMAT);
8592     }
8593     b2_config = READ_WORD(mdm_config[0].info);
8594   }
8595
8596   /* OK, L2 is modem */
8597
8598   lli[0] = 1;
8599   lli[1] = 1;
8600   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8601     lli[1] |= 2;
8602   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8603     lli[1] |= 4;
8604
8605   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8606     lli[1] |= 0x10;
8607     if (plci->rx_dma_descriptor <= 0) {
8608       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8609       if (plci->rx_dma_descriptor >= 0)
8610         plci->rx_dma_descriptor++;
8611     }
8612     if (plci->rx_dma_descriptor > 0) {
8613       lli[1] |= 0x40;
8614       lli[0] = 6;
8615       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8616       lli[3] = (byte)plci->rx_dma_magic;
8617       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8618       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8619       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8620     }
8621   }
8622
8623   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8624     lli[1] |= 0x20;
8625   }
8626
8627   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8628     /*V42*/ 10 : /*V42_IN*/ 9;
8629   llc[2] = 4;                      /* pass L3 always transparent */
8630   add_p(plci, LLI, lli);
8631   add_p(plci, LLC, llc);
8632   i =  1;
8633   WRITE_WORD (&dlc[i], plci->appl->MaxDataLength);
8634   i += 2;
8635   if (READ_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8636   {
8637     if (bp_parms[4].length)
8638   {
8639     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8640     dlc[i++] = 3; /* Addr A */
8641     dlc[i++] = 1; /* Addr B */
8642     dlc[i++] = 7; /* modulo mode */
8643     dlc[i++] = 7; /* window size */
8644     dlc[i++] = 0; /* XID len Lo  */
8645     dlc[i++] = 0; /* XID len Hi  */
8646
8647     if (b2_config & MDM_B2_DISABLE_V42bis)
8648     {
8649       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8650     }
8651     if (b2_config & MDM_B2_DISABLE_MNP)
8652     {
8653       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8654     }
8655     if (b2_config & MDM_B2_DISABLE_TRANS)
8656     {
8657       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8658     }
8659     if (b2_config & MDM_B2_DISABLE_V42)
8660     {
8661       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8662     }
8663     if (b2_config & MDM_B2_DISABLE_COMP)
8664     {
8665       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8666     }
8667     i++;
8668   }
8669   }
8670   else
8671   {
8672     dlc[i++] = 3; /* Addr A */
8673     dlc[i++] = 1; /* Addr B */
8674     dlc[i++] = 7; /* modulo mode */
8675     dlc[i++] = 7; /* window size */
8676     dlc[i++] = 0; /* XID len Lo  */
8677     dlc[i++] = 0; /* XID len Hi  */
8678     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8679                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8680                DLC_MODEMPROT_DISABLE_V42_DETECT |
8681                DLC_MODEMPROT_DISABLE_COMPRESSION;
8682   }
8683   dlc[0] = (byte)(i - 1);
8684 //HexDump ("DLC", sizeof(dlc), &dlc[0]);
8685   add_p(plci, DLC, dlc);
8686   return (0);
8687 }
8688
8689
8690 /*------------------------------------------------------------------*/
8691 /* send a request for the signaling entity                          */
8692 /*------------------------------------------------------------------*/
8693
8694 void sig_req(PLCI   * plci, byte req, byte Id)
8695 {
8696   if(!plci) return;
8697   if(plci->adapter->adapter_disabled) return;
8698   dbug(1,dprintf("sig_req(%x)",req));
8699   if (req == REMOVE)
8700     plci->sig_remove_id = plci->Sig.Id;
8701   if(plci->req_in==plci->req_in_start) {
8702     plci->req_in +=2;
8703     plci->RBuffer[plci->req_in++] = 0;
8704   }
8705   WRITE_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8706   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8707   plci->RBuffer[plci->req_in++] = req;  /* request */
8708   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8709   plci->req_in_start = plci->req_in;
8710 }
8711
8712 /*------------------------------------------------------------------*/
8713 /* send a request for the network layer entity                      */
8714 /*------------------------------------------------------------------*/
8715
8716 void nl_req_ncci(PLCI   * plci, byte req, byte ncci)
8717 {
8718   if(!plci) return;
8719   if(plci->adapter->adapter_disabled) return;
8720   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8721   if (req == REMOVE)
8722   {
8723     plci->nl_remove_id = plci->NL.Id;
8724     ncci_remove (plci, 0, (byte)(ncci != 0));
8725     ncci = 0;
8726   }
8727   if(plci->req_in==plci->req_in_start) {
8728     plci->req_in +=2;
8729     plci->RBuffer[plci->req_in++] = 0;
8730   }
8731   WRITE_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8732   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8733   plci->RBuffer[plci->req_in++] = req;  /* request */
8734   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8735   plci->req_in_start = plci->req_in;
8736 }
8737
8738 void send_req(PLCI   * plci)
8739 {
8740   ENTITY   * e;
8741   word l;
8742 //  word i;
8743
8744   if(!plci) return;
8745   if(plci->adapter->adapter_disabled) return;
8746   channel_xmit_xon (plci);
8747
8748         /* if nothing to do, return */
8749   if(plci->req_in==plci->req_out) return;
8750   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8751
8752   if(plci->nl_req || plci->sig_req) return;
8753
8754   l = READ_WORD(&plci->RBuffer[plci->req_out]);
8755   plci->req_out += 2;
8756   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8757   plci->req_out += l;
8758   if(plci->RBuffer[plci->req_out]==1)
8759   {
8760     e = &plci->NL;
8761     plci->req_out++;
8762     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8763     e->ReqCh = plci->RBuffer[plci->req_out++];
8764     if(!(e->Id & 0x1f))
8765     {
8766       e->Id = NL_ID;
8767       plci->RBuffer[plci->req_out-4] = CAI;
8768       plci->RBuffer[plci->req_out-3] = 1;
8769       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8770       plci->RBuffer[plci->req_out-1] = 0;
8771       l+=3;
8772       plci->nl_global_req = plci->nl_req;
8773     }
8774     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8775   }
8776   else
8777   {
8778     e = &plci->Sig;
8779     if(plci->RBuffer[plci->req_out])
8780       e->Id = plci->RBuffer[plci->req_out];
8781     plci->req_out++;
8782     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8783     e->ReqCh = plci->RBuffer[plci->req_out++];
8784     if(!(e->Id & 0x1f))
8785       plci->sig_global_req = plci->sig_req;
8786     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8787   }
8788   plci->XData[0].PLength = l;
8789   e->X = plci->XData;
8790   plci->adapter->request(e);
8791   dbug(1,dprintf("send_ok"));
8792 }
8793
8794 void send_data(PLCI   * plci)
8795 {
8796   DIVA_CAPI_ADAPTER   * a;
8797   DATA_B3_DESC   * data;
8798   NCCI   *ncci_ptr;
8799   word ncci;
8800
8801   if (!plci->nl_req && plci->ncci_ring_list)
8802   {
8803     a = plci->adapter;
8804     ncci = plci->ncci_ring_list;
8805     do
8806     {
8807       ncci = a->ncci_next[ncci];
8808       ncci_ptr = &(a->ncci[ncci]);
8809       if (!(a->ncci_ch[ncci]
8810          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8811       {
8812         if (ncci_ptr->data_pending)
8813         {
8814           if ((a->ncci_state[ncci] == CONNECTED)
8815            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8816            || (plci->send_disc == ncci))
8817           {
8818             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8819             if ((plci->B2_prot == B2_V120_ASYNC)
8820              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8821              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8822             {
8823               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8824               plci->NData[1].PLength = data->Length;
8825               if (data->Flags & 0x10)
8826                 plci->NData[0].P = v120_break_header;
8827               else
8828                 plci->NData[0].P = v120_default_header;
8829               plci->NData[0].PLength = 1 ;
8830               plci->NL.XNum = 2;
8831               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8832             }
8833             else
8834             {
8835               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8836               plci->NData[0].PLength = data->Length;
8837               if (data->Flags & 0x10)
8838                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8839
8840               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8841                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8842
8843               else
8844                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8845             }
8846             plci->NL.X = plci->NData;
8847             plci->NL.ReqCh = a->ncci_ch[ncci];
8848             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8849             plci->data_sent = TRUE;
8850             plci->data_sent_ptr = data->P;
8851             a->request(&plci->NL);
8852           }
8853           else {
8854             cleanup_ncci_data (plci, ncci);
8855           }
8856         }
8857         else if (plci->send_disc == ncci)
8858         {
8859           //dprintf("N_DISC");
8860           plci->NData[0].PLength = 0;
8861           plci->NL.ReqCh = a->ncci_ch[ncci];
8862           plci->NL.Req = plci->nl_req = N_DISC;
8863           a->request(&plci->NL);
8864           plci->command = _DISCONNECT_B3_R;
8865           plci->send_disc = 0;
8866         }
8867       }
8868     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8869     plci->ncci_ring_list = ncci;
8870   }
8871 }
8872
8873 void listen_check(DIVA_CAPI_ADAPTER   * a)
8874 {
8875   word i,j;
8876   PLCI   * plci;
8877   byte activnotifiedcalls = 0;
8878
8879   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8880   if (!remove_started && !a->adapter_disabled)
8881   {
8882     for(i=0;i<a->max_plci;i++)
8883     {
8884       plci = &(a->plci[i]);
8885       if(plci->notifiedcall) activnotifiedcalls++;
8886     }
8887     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8888
8889     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8890       if((j=get_plci(a))) {
8891         a->listen_active++;
8892         plci = &a->plci[j-1];
8893         plci->State = LISTENING;
8894
8895         add_p(plci,OAD,"\x01\xfd");
8896
8897         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8898
8899         add_p(plci,CAI,"\x01\xc0");
8900         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8901         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8902         add_p(plci,SHIFT|6,0);
8903         add_p(plci,SIN,"\x02\x00\x00");
8904         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8905         sig_req(plci,ASSIGN,DSIG_ID);
8906         send_req(plci);
8907       }
8908     }
8909   }
8910 }
8911
8912 /*------------------------------------------------------------------*/
8913 /* functions for all parameters sent in INDs                        */
8914 /*------------------------------------------------------------------*/
8915
8916 void IndParse(PLCI   * plci, word * parms_id, byte   ** parms, byte multiIEsize)
8917 {
8918   word ploc;            /* points to current location within packet */
8919   byte w;
8920   byte wlen;
8921   byte codeset,lock;
8922   byte   * in;
8923   word i;
8924   word code;
8925   word mIEindex = 0;
8926   ploc = 0;
8927   codeset = 0;
8928   lock = 0;
8929
8930   in = plci->Sig.RBuffer->P;
8931   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8932   {                            /* element but parms array is larger      */
8933     parms[i] = (byte   *)"";
8934   }
8935   for(i=0; i<multiIEsize; i++)
8936   {
8937     parms[i] = (byte   *)"";
8938   }
8939
8940   while(ploc<plci->Sig.RBuffer->length-1) {
8941
8942         /* read information element id and length                   */
8943     w = in[ploc];
8944
8945     if(w & 0x80) {
8946 /*    w &=0xf0; removed, cannot detect congestion levels */
8947 /*    upper 4 bit masked with w==SHIFT now               */
8948       wlen = 0;
8949     }
8950     else {
8951       wlen = (byte)(in[ploc+1]+1);
8952     }
8953         /* check if length valid (not exceeding end of packet)      */
8954     if((ploc+wlen) > 270) return ;
8955     if(lock & 0x80) lock &=0x7f;
8956     else codeset = lock;
8957
8958     if((w&0xf0)==SHIFT) {
8959       codeset = in[ploc];
8960       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8961       codeset &=7;
8962       lock |=0x80;
8963     }
8964     else {
8965       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8966       else code = w;
8967       code |= (codeset<<8);
8968
8969       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8970
8971       if(i<parms_id[0]+1) {
8972         if(!multiIEsize) { /* with multiIEs use next field index,          */
8973           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8974         }
8975
8976         parms[mIEindex] = &in[ploc+1];
8977         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8978         if(parms_id[i]==OAD
8979         || parms_id[i]==CONN_NR
8980         || parms_id[i]==CAD) {
8981           if(in[ploc+2] &0x80) {
8982             in[ploc+0] = (byte)(in[ploc+1]+1);
8983             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8984             in[ploc+2] = 0x80;
8985             parms[mIEindex] = &in[ploc];
8986           }
8987         }
8988         mIEindex++;       /* effects multiIEs only */
8989       }
8990     }
8991
8992     ploc +=(wlen+1);
8993   }
8994   return ;
8995 }
8996
8997 /*------------------------------------------------------------------*/
8998 /* try to match a cip from received BC and HLC                      */
8999 /*------------------------------------------------------------------*/
9000
9001 byte ie_compare(byte   * ie1, byte * ie2)
9002 {
9003   word i;
9004   if(!ie1 || ! ie2) return FALSE;
9005   if(!ie1[0]) return FALSE;
9006   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return FALSE;
9007   return TRUE;
9008 }
9009
9010 word find_cip(DIVA_CAPI_ADAPTER   * a, byte   * bc, byte   * hlc)
9011 {
9012   word i;
9013   word j;
9014
9015   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9016
9017   for(j=16;j<29 &&
9018            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9019   if(j==29) return i;
9020   return j;
9021 }
9022
9023
9024 static byte AddInfo(byte   **add_i,
9025                     byte   **fty_i,
9026                     byte   *esc_chi,
9027                     byte *facility)
9028 {
9029   byte i;
9030   byte j;
9031   byte k;
9032   byte flen;
9033   byte len=0;
9034    /* facility is a nested structure */
9035    /* FTY can be more than once      */
9036
9037   if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9038   {
9039     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9040   }
9041
9042   else
9043   {
9044     add_i[0] = (byte   *)"";
9045   }
9046   if(!fty_i[0][0])
9047   {
9048     add_i[3] = (byte   *)"";
9049   }
9050   else
9051   {    /* facility array found  */
9052     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9053     {
9054       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9055       len += fty_i[i][0];
9056       len += 2;
9057       flen=fty_i[i][0];
9058       facility[j++]=0x1c; /* copy fac IE */
9059       for(k=0;k<=flen;k++,j++)
9060       {
9061         facility[j]=fty_i[i][k];
9062 //      dbug(1,dprintf("%x ",facility[j]));
9063       }
9064     }
9065     facility[0] = len;
9066     add_i[3] = facility;
9067   }
9068 //  dbug(1,dprintf("FacArrLen=%d ",len));
9069   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9070   len += 4;                          // calculate length of all
9071   return(len);
9072 }
9073
9074 /*------------------------------------------------------------------*/
9075 /* voice and codec features                                         */
9076 /*------------------------------------------------------------------*/
9077
9078 void SetVoiceChannel(PLCI   *plci, byte   *chi, DIVA_CAPI_ADAPTER   * a)
9079 {
9080   byte voice_chi[] = "\x02\x18\x01";
9081   byte channel;
9082
9083   channel = chi[chi[0]]&0x3;
9084   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9085   voice_chi[2] = (channel) ? channel : 1;
9086   add_p(plci,FTY,"\x02\x01\x07");             // B On, default on 1
9087   add_p(plci,ESC,voice_chi);                  // Channel
9088   sig_req(plci,TEL_CTRL,0);
9089   send_req(plci);
9090   if(a->AdvSignalPLCI)
9091   {
9092     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9093   }
9094 }
9095
9096 void VoiceChannelOff(PLCI   *plci)
9097 {
9098   dbug(1,dprintf("ExtDevOFF"));
9099   add_p(plci,FTY,"\x02\x01\x08");             // B Off
9100   sig_req(plci,TEL_CTRL,0);
9101   send_req(plci);
9102   if(plci->adapter->AdvSignalPLCI)
9103   {
9104     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9105   }
9106 }
9107
9108
9109 word AdvCodecSupport(DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, byte hook_listen)
9110 {
9111   word j;
9112   PLCI   *splci;
9113
9114   /* check if hardware supports handset with hook states (adv.codec) */
9115   /* or if just a on board codec is supported                        */
9116   /* the advanced codec plci is just for internal use                */
9117
9118   /* diva Pro with on-board codec:                                   */
9119   if(a->profile.Global_Options & HANDSET)
9120   {
9121     /* new call, but hook states are already signalled */
9122     if(a->AdvCodecFLAG)
9123     {
9124       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9125       {
9126         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9127         return 0x2001; /* codec in use by another application */
9128       }
9129       if(plci!=0)
9130       {
9131         a->AdvSignalPLCI = plci;
9132         plci->tel=ADV_VOICE;
9133       }
9134       return 0;                      /* adv codec still used */
9135     }
9136     if((j=get_plci(a)))
9137     {
9138       splci = &a->plci[j-1];
9139       splci->tel = CODEC_PERMANENT;
9140       /* hook_listen indicates if a facility_req with handset/hook support */
9141       /* was sent. Otherwise if just a call on an external device was made */
9142       /* the codec will be used but the hook info will be discarded (just  */
9143       /* the external controller is in use                                 */
9144       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9145       else
9146       {
9147         splci->State = ADVANCED_VOICE_NOSIG;
9148         if(plci)
9149         {
9150           plci->spoofed_msg = SPOOFING_REQUIRED;
9151         }
9152                                                /* indicate D-ch connect if  */
9153       }                                        /* codec is connected OK     */
9154       if(plci!=0)
9155       {
9156         a->AdvSignalPLCI = plci;
9157         plci->tel=ADV_VOICE;
9158       }
9159       a->AdvSignalAppl = appl;
9160       a->AdvCodecFLAG = TRUE;
9161       a->AdvCodecPLCI = splci;
9162       add_p(splci,CAI,"\x01\x15");
9163       add_p(splci,LLI,"\x01\x00");
9164       add_p(splci,ESC,"\x02\x18\x00");
9165       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9166       splci->internal_command = PERM_COD_ASSIGN;
9167       dbug(1,dprintf("Codec Assign"));
9168       sig_req(splci,ASSIGN,DSIG_ID);
9169       send_req(splci);
9170     }
9171     else
9172     {
9173       return 0x2001; /* wrong state, no more plcis */
9174     }
9175   }
9176   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9177   {
9178     if(hook_listen) return 0x300B;               /* Facility not supported */
9179                                                  /* no hook with SCOM      */
9180     if(plci!=0) plci->tel = CODEC;
9181     dbug(1,dprintf("S/SCOM codec"));
9182     /* first time we use the scom-s codec we must shut down the internal   */
9183     /* handset application of the card. This can be done by an assign with */
9184     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9185     if(!a->scom_appl_disable){
9186       if((j=get_plci(a))) {
9187         splci = &a->plci[j-1];
9188         add_p(splci,CAI,"\x01\x80");
9189         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9190         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9191         send_req(splci);
9192         a->scom_appl_disable = TRUE;
9193       }
9194       else{
9195         return 0x2001; /* wrong state, no more plcis */
9196       }
9197     }
9198   }
9199   else return 0x300B;               /* Facility not supported */
9200
9201   return 0;
9202 }
9203
9204
9205 void CodecIdCheck(DIVA_CAPI_ADAPTER   *a, PLCI   *plci)
9206 {
9207
9208   dbug(1,dprintf("CodecIdCheck"));
9209
9210   if(a->AdvSignalPLCI == plci)
9211   {
9212     dbug(1,dprintf("PLCI owns codec"));
9213     VoiceChannelOff(a->AdvCodecPLCI);
9214     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9215     {
9216       dbug(1,dprintf("remove temp codec PLCI"));
9217       plci_remove(a->AdvCodecPLCI);
9218       a->AdvCodecFLAG  = 0;
9219       a->AdvCodecPLCI  = 0;
9220       a->AdvSignalAppl = 0;
9221     }
9222     a->AdvSignalPLCI = 0;
9223   }
9224 }
9225
9226 /* -------------------------------------------------------------------
9227     Ask for physical address of card on PCI bus
9228    ------------------------------------------------------------------- */
9229 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9230                                         IDI_SYNC_REQ  * preq) {
9231   a->sdram_bar = 0;
9232   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9233     ENTITY   * e = (ENTITY   *)preq;
9234
9235     e->user[0] = a->Id - 1;
9236     preq->xdi_sdram_bar.info.bar    = 0;
9237     preq->xdi_sdram_bar.Req         = 0;
9238     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9239
9240     (*(a->request))(e);
9241
9242     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9243     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9244   }
9245 }
9246
9247 /* -------------------------------------------------------------------
9248      Ask XDI about extended features
9249    ------------------------------------------------------------------- */
9250 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9251   IDI_SYNC_REQ   * preq;
9252     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9253
9254     char features[4];
9255   preq = (IDI_SYNC_REQ   *)&buffer[0];
9256
9257   if (!diva_xdi_extended_features) {
9258     ENTITY   * e = (ENTITY   *)preq;
9259     diva_xdi_extended_features |= 0x80000000;
9260
9261     e->user[0] = a->Id - 1;
9262     preq->xdi_extended_features.Req = 0;
9263     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9264     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9265     preq->xdi_extended_features.info.features = &features[0];
9266
9267     (*(a->request))(e);
9268
9269     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9270       /*
9271          Check features located in the byte '0'
9272          */
9273       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9274         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9275       }
9276       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9277         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9278         dbug(1,dprintf("XDI provides RxDMA"));
9279       }
9280       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9281         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9282       }
9283       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9284         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9285         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9286       }
9287
9288     }
9289   }
9290
9291   diva_ask_for_xdi_sdram_bar (a, preq);
9292 }
9293
9294 /*------------------------------------------------------------------*/
9295 /* automatic law                                                    */
9296 /*------------------------------------------------------------------*/
9297 /* called from OS specific part after init time to get the Law              */
9298 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9299 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9300 {
9301   word j;
9302   PLCI   *splci;
9303
9304   if(a->automatic_law) {
9305     return;
9306   }
9307   if((j=get_plci(a))) {
9308     diva_get_extended_adapter_features (a);
9309     splci = &a->plci[j-1];
9310     a->automatic_lawPLCI = splci;
9311     a->automatic_law = 1;
9312     add_p(splci,CAI,"\x01\x80");
9313     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9314     splci->internal_command = USELAW_REQ;
9315     splci->command = 0;
9316     splci->number = 0;
9317     sig_req(splci,ASSIGN,DSIG_ID);
9318     send_req(splci);
9319   }
9320 }
9321
9322 /* called from OS specific part if an application sends an Capi20Release */
9323 word CapiRelease(word Id)
9324 {
9325   word i, j, appls_found;
9326   PLCI   *plci;
9327   APPL   *this;
9328   DIVA_CAPI_ADAPTER   *a;
9329
9330   if (!Id)
9331   {
9332     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9333     return (_WRONG_APPL_ID);
9334   }
9335
9336   this = &application[Id-1];               /* get application pointer */
9337
9338   for(i=0,appls_found=0; i<max_appl; i++)
9339   {
9340     if(application[i].Id)       /* an application has been found        */
9341     {
9342       appls_found++;
9343     }
9344   }
9345
9346   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9347   {
9348     a = &adapter[i];
9349     if (a->request)
9350     {
9351       a->Info_Mask[Id-1] = 0;
9352       a->CIP_Mask[Id-1] = 0;
9353       a->Notification_Mask[Id-1] = 0;
9354       a->codec_listen[Id-1] = 0;
9355       a->requested_options_table[Id-1] = 0;
9356       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9357       {                                      /* with this application   */
9358         plci = &a->plci[j];
9359         if(plci->Id)                         /* if plci owns no application */
9360         {                                    /* it may be not jet connected */
9361           if(plci->State==INC_CON_PENDING
9362           || plci->State==INC_CON_ALERT)
9363           {
9364             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9365             {
9366               clear_c_ind_mask_bit (plci, (word)(Id-1));
9367               if(c_ind_mask_empty (plci))
9368               {
9369                 sig_req(plci,HANGUP,0);
9370                 send_req(plci);
9371                 plci->State = OUTG_DIS_PENDING;
9372               }
9373             }
9374           }
9375           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9376           {
9377             clear_c_ind_mask_bit (plci, (word)(Id-1));
9378             if(c_ind_mask_empty (plci))
9379             {
9380               if(!plci->appl)
9381               {
9382                 plci_remove(plci);
9383                 plci->State = IDLE;
9384               }
9385             }
9386           }
9387           if(plci->appl==this)
9388           {
9389             plci->appl = 0;
9390             plci_remove(plci);
9391             plci->State = IDLE;
9392           }
9393         }
9394       }
9395       listen_check(a);
9396
9397       if(a->flag_dynamic_l1_down)
9398       {
9399         if(appls_found==1)            /* last application does a capi release */
9400         {
9401           if((j=get_plci(a)))
9402           {
9403             plci = &a->plci[j-1];
9404             plci->command = 0;
9405             add_p(plci,OAD,"\x01\xfd");
9406             add_p(plci,CAI,"\x01\x80");
9407             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9408             add_p(plci,SHIFT|6,0);
9409             add_p(plci,SIN,"\x02\x00\x00");
9410             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9411             sig_req(plci,ASSIGN,DSIG_ID);
9412             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9413             sig_req(plci,SIG_CTRL,0);
9414             send_req(plci);
9415           }
9416         }
9417       }
9418       if(a->AdvSignalAppl==this)
9419       {
9420         this->NullCREnable = FALSE;
9421         if (a->AdvCodecPLCI)
9422         {
9423           plci_remove(a->AdvCodecPLCI);
9424           a->AdvCodecPLCI->tel = 0;
9425           a->AdvCodecPLCI->adv_nl = 0;
9426         }
9427         a->AdvSignalAppl = 0;
9428         a->AdvSignalPLCI = 0;
9429         a->AdvCodecFLAG = 0;
9430         a->AdvCodecPLCI = 0;
9431       }
9432     }
9433   }
9434
9435   this->Id = 0;
9436
9437   return GOOD;
9438 }
9439
9440 static word plci_remove_check(PLCI   *plci)
9441 {
9442   if(!plci) return TRUE;
9443   if(!plci->NL.Id && c_ind_mask_empty (plci))
9444   {
9445     if(plci->Sig.Id == 0xff)
9446       plci->Sig.Id = 0;
9447     if(!plci->Sig.Id)
9448     {
9449       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9450       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9451       if (plci->Id)
9452       {
9453         CodecIdCheck(plci->adapter, plci);
9454         clear_b1_config (plci);
9455         ncci_remove (plci, 0, FALSE);
9456         plci_free_msg_in_queue (plci);
9457         channel_flow_control_remove (plci);
9458         plci->Id = 0;
9459         plci->State = IDLE;
9460         plci->channels = 0;
9461         plci->appl = 0;
9462         plci->notifiedcall = 0;
9463       }
9464       listen_check(plci->adapter);
9465       return TRUE;
9466     }
9467   }
9468   return FALSE;
9469 }
9470
9471
9472 /*------------------------------------------------------------------*/
9473
9474 static byte plci_nl_busy (PLCI   *plci)
9475 {
9476   /* only applicable for non-multiplexed protocols */
9477   return (plci->nl_req
9478     || (plci->ncci_ring_list
9479      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9480      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9481 }
9482
9483
9484 /*------------------------------------------------------------------*/
9485 /* DTMF facilities                                                  */
9486 /*------------------------------------------------------------------*/
9487
9488
9489 static struct
9490 {
9491   byte send_mask;
9492   byte listen_mask;
9493   byte character;
9494   byte code;
9495 } dtmf_digit_map[] =
9496 {
9497   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9498   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9499   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9500   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9501   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9502   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9503   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9504   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9505   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9506   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9507   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9508   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9509   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9510   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9511   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9512   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9513   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9514   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9515   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9516   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9517
9518   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9519   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9520   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9521   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9522   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9523   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9524   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9525   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9526   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9527   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9528   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9529   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9530   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9531   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9532   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9533   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9534   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9535   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9536   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9537   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9538   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9539   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9540   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9541   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9542   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9543   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9544   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9545   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9546   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9547   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9548   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9549   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9550   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9551   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9552   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9553   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9554   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9555   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9556   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9557   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9558   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9559   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9560   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9561   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9562   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9563   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9564   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9565   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9566   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9567   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9568   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9569   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9570
9571 };
9572
9573 #define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0]))
9574
9575
9576 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9577 {
9578   word min_digit_duration, min_gap_duration;
9579
9580   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9581     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9582     (char   *)(FILE_), __LINE__, enable_mask));
9583
9584   if (enable_mask != 0)
9585   {
9586     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9587     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9588     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9589     WRITE_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9590     WRITE_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9591     plci->NData[0].PLength = 5;
9592
9593     WRITE_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9594     plci->NData[0].PLength += 2;
9595     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9596
9597   }
9598   else
9599   {
9600     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9601     plci->NData[0].PLength = 1;
9602
9603     capidtmf_recv_disable (&(plci->capidtmf_state));
9604
9605   }
9606   plci->NData[0].P = plci->internal_req_buffer;
9607   plci->NL.X = plci->NData;
9608   plci->NL.ReqCh = 0;
9609   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9610   plci->adapter->request (&plci->NL);
9611 }
9612
9613
9614 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9615 {
9616   word w, i;
9617
9618   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9619     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9620     (char   *)(FILE_), __LINE__, digit_count));
9621
9622   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9623   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9624   WRITE_WORD (&plci->internal_req_buffer[1], w);
9625   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9626   WRITE_WORD (&plci->internal_req_buffer[3], w);
9627   for (i = 0; i < digit_count; i++)
9628   {
9629     w = 0;
9630     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9631       && (digit_buffer[i] != dtmf_digit_map[w].character))
9632     {
9633       w++;
9634     }
9635     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9636       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9637   }
9638   plci->NData[0].PLength = 5 + digit_count;
9639   plci->NData[0].P = plci->internal_req_buffer;
9640   plci->NL.X = plci->NData;
9641   plci->NL.ReqCh = 0;
9642   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9643   plci->adapter->request (&plci->NL);
9644 }
9645
9646
9647 static void dtmf_rec_clear_config (PLCI   *plci)
9648 {
9649
9650   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9651     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9652     (char   *)(FILE_), __LINE__));
9653
9654   plci->dtmf_rec_active = 0;
9655   plci->dtmf_rec_pulse_ms = 0;
9656   plci->dtmf_rec_pause_ms = 0;
9657
9658   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9659
9660 }
9661
9662
9663 static void dtmf_send_clear_config (PLCI   *plci)
9664 {
9665
9666   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9667     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9668     (char   *)(FILE_), __LINE__));
9669
9670   plci->dtmf_send_requests = 0;
9671   plci->dtmf_send_pulse_ms = 0;
9672   plci->dtmf_send_pause_ms = 0;
9673 }
9674
9675
9676 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9677 {
9678
9679   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9680     UnMapId (Id), (char   *)(FILE_), __LINE__));
9681
9682   while (plci->dtmf_send_requests != 0)
9683     dtmf_confirmation (Id, plci);
9684 }
9685
9686
9687 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9688 {
9689
9690   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9691     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9692
9693   return (GOOD);
9694 }
9695
9696
9697 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9698 {
9699   word Info;
9700
9701   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9702     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9703
9704   Info = GOOD;
9705   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9706   {
9707     switch (plci->adjust_b_state)
9708     {
9709     case ADJUST_B_RESTORE_DTMF_1:
9710       plci->internal_command = plci->adjust_b_command;
9711       if (plci_nl_busy (plci))
9712       {
9713         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9714         break;
9715       }
9716       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9717       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9718       break;
9719     case ADJUST_B_RESTORE_DTMF_2:
9720       if ((Rc != OK) && (Rc != OK_FC))
9721       {
9722         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9723           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9724         Info = _WRONG_STATE;
9725         break;
9726       }
9727       break;
9728     }
9729   }
9730   return (Info);
9731 }
9732
9733
9734 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9735 {
9736   word internal_command, Info;
9737   byte mask;
9738     byte result[4];
9739
9740   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9741     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9742     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9743     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9744
9745   Info = GOOD;
9746   result[0] = 2;
9747   WRITE_WORD (&result[1], DTMF_SUCCESS);
9748   internal_command = plci->internal_command;
9749   plci->internal_command = 0;
9750   mask = 0x01;
9751   switch (plci->dtmf_cmd)
9752   {
9753
9754   case DTMF_LISTEN_TONE_START:
9755     mask <<= 1;
9756   case DTMF_LISTEN_MF_START:
9757     mask <<= 1;
9758
9759   case DTMF_LISTEN_START:
9760     switch (internal_command)
9761     {
9762     default:
9763       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9764         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9765     case DTMF_COMMAND_1:
9766       if (adjust_b_process (Id, plci, Rc) != GOOD)
9767       {
9768         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9769           UnMapId (Id), (char   *)(FILE_), __LINE__));
9770         Info = _FACILITY_NOT_SUPPORTED;
9771         break;
9772       }
9773       if (plci->internal_command)
9774         return;
9775     case DTMF_COMMAND_2:
9776       if (plci_nl_busy (plci))
9777       {
9778         plci->internal_command = DTMF_COMMAND_2;
9779         return;
9780       }
9781       plci->internal_command = DTMF_COMMAND_3;
9782       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9783       return;
9784     case DTMF_COMMAND_3:
9785       if ((Rc != OK) && (Rc != OK_FC))
9786       {
9787         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9788           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9789         Info = _FACILITY_NOT_SUPPORTED;
9790         break;
9791       }
9792
9793       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9794
9795       plci->dtmf_rec_active |= mask;
9796       break;
9797     }
9798     break;
9799
9800
9801   case DTMF_LISTEN_TONE_STOP:
9802     mask <<= 1;
9803   case DTMF_LISTEN_MF_STOP:
9804     mask <<= 1;
9805
9806   case DTMF_LISTEN_STOP:
9807     switch (internal_command)
9808     {
9809     default:
9810       plci->dtmf_rec_active &= ~mask;
9811       if (plci->dtmf_rec_active)
9812         break;
9813 /*
9814     case DTMF_COMMAND_1:
9815       if (plci->dtmf_rec_active)
9816       {
9817         if (plci_nl_busy (plci))
9818         {
9819           plci->internal_command = DTMF_COMMAND_1;
9820           return;
9821         }
9822         plci->dtmf_rec_active &= ~mask;
9823         plci->internal_command = DTMF_COMMAND_2;
9824         dtmf_enable_receiver (plci, FALSE);
9825         return;
9826       }
9827       Rc = OK;
9828     case DTMF_COMMAND_2:
9829       if ((Rc != OK) && (Rc != OK_FC))
9830       {
9831         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9832           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9833         Info = _FACILITY_NOT_SUPPORTED;
9834         break;
9835       }
9836 */
9837       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9838         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9839     case DTMF_COMMAND_3:
9840       if (adjust_b_process (Id, plci, Rc) != GOOD)
9841       {
9842         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9843           UnMapId (Id), (char   *)(FILE_), __LINE__));
9844         Info = _FACILITY_NOT_SUPPORTED;
9845         break;
9846       }
9847       if (plci->internal_command)
9848         return;
9849       break;
9850     }
9851     break;
9852
9853
9854   case DTMF_SEND_TONE:
9855     mask <<= 1;
9856   case DTMF_SEND_MF:
9857     mask <<= 1;
9858
9859   case DTMF_DIGITS_SEND:
9860     switch (internal_command)
9861     {
9862     default:
9863       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9864         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9865         DTMF_COMMAND_1);
9866     case DTMF_COMMAND_1:
9867       if (adjust_b_process (Id, plci, Rc) != GOOD)
9868       {
9869         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9870           UnMapId (Id), (char   *)(FILE_), __LINE__));
9871         Info = _FACILITY_NOT_SUPPORTED;
9872         break;
9873       }
9874       if (plci->internal_command)
9875         return;
9876     case DTMF_COMMAND_2:
9877       if (plci_nl_busy (plci))
9878       {
9879         plci->internal_command = DTMF_COMMAND_2;
9880         return;
9881       }
9882       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9883       plci->internal_command = DTMF_COMMAND_3;
9884       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9885       return;
9886     case DTMF_COMMAND_3:
9887       if ((Rc != OK) && (Rc != OK_FC))
9888       {
9889         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9890           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9891         if (plci->dtmf_send_requests != 0)
9892           (plci->dtmf_send_requests)--;
9893         Info = _FACILITY_NOT_SUPPORTED;
9894         break;
9895       }
9896       return;
9897     }
9898     break;
9899   }
9900   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9901     "wws", Info, SELECTOR_DTMF, result);
9902 }
9903
9904
9905 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9906 {
9907   word Info;
9908   word i, j;
9909   byte mask;
9910     API_PARSE dtmf_parms[5];
9911     byte result[40];
9912
9913   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9914     UnMapId (Id), (char   *)(FILE_), __LINE__));
9915
9916   Info = GOOD;
9917   result[0] = 2;
9918   WRITE_WORD (&result[1], DTMF_SUCCESS);
9919   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9920   {
9921     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9922       UnMapId (Id), (char   *)(FILE_), __LINE__));
9923     Info = _FACILITY_NOT_SUPPORTED;
9924   }
9925   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9926   {
9927     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9928       UnMapId (Id), (char   *)(FILE_), __LINE__));
9929     Info = _WRONG_MESSAGE_FORMAT;
9930   }
9931
9932   else if ((READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9933     || (READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9934   {
9935     if (!((a->requested_options_table[appl->Id-1])
9936         & (1L << PRIVATE_DTMF_TONE)))
9937     {
9938       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9939         UnMapId (Id), (char   *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info)));
9940       WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9941     }
9942     else
9943     {
9944       for (i = 0; i < 32; i++)
9945         result[4 + i] = 0;
9946       if (READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947       {
9948         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9949         {
9950           if (dtmf_digit_map[i].listen_mask != 0)
9951             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9952         }
9953       }
9954       else
9955       {
9956         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9957         {
9958           if (dtmf_digit_map[i].send_mask != 0)
9959             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9960         }
9961       }
9962       result[0] = 3 + 32;
9963       result[3] = 32;
9964     }
9965   }
9966
9967   else if (plci == NULL)
9968   {
9969     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9970       UnMapId (Id), (char   *)(FILE_), __LINE__));
9971     Info = _WRONG_IDENTIFIER;
9972   }
9973   else
9974   {
9975     if (!plci->State
9976      || !plci->NL.Id || plci->nl_remove_id)
9977     {
9978       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9979         UnMapId (Id), (char   *)(FILE_), __LINE__));
9980       Info = _WRONG_STATE;
9981     }
9982     else
9983     {
9984       plci->command = 0;
9985       plci->dtmf_cmd = READ_WORD (dtmf_parms[0].info);
9986       mask = 0x01;
9987       switch (plci->dtmf_cmd)
9988       {
9989
9990       case DTMF_LISTEN_TONE_START:
9991       case DTMF_LISTEN_TONE_STOP:
9992         mask <<= 1;
9993       case DTMF_LISTEN_MF_START:
9994       case DTMF_LISTEN_MF_STOP:
9995         mask <<= 1;
9996         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9997           & (1L << PRIVATE_DTMF_TONE)))
9998         {
9999           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10000             UnMapId (Id), (char   *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info)));
10001           WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10002           break;
10003         }
10004
10005       case DTMF_LISTEN_START:
10006       case DTMF_LISTEN_STOP:
10007         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10008          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10009         {
10010           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10011             UnMapId (Id), (char   *)(FILE_), __LINE__));
10012           Info = _FACILITY_NOT_SUPPORTED;
10013           break;
10014         }
10015         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10016         {
10017           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10018           {
10019             plci->dtmf_rec_pulse_ms = 0;
10020             plci->dtmf_rec_pause_ms = 0;
10021           }
10022           else
10023           {
10024             plci->dtmf_rec_pulse_ms = READ_WORD (dtmf_parms[1].info);
10025             plci->dtmf_rec_pause_ms = READ_WORD (dtmf_parms[2].info);
10026           }
10027         }
10028         start_internal_command (Id, plci, dtmf_command);
10029         return (FALSE);
10030
10031
10032       case DTMF_SEND_TONE:
10033         mask <<= 1;
10034       case DTMF_SEND_MF:
10035         mask <<= 1;
10036         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10037           & (1L << PRIVATE_DTMF_TONE)))
10038         {
10039           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10040             UnMapId (Id), (char   *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info)));
10041           WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10042           break;
10043         }
10044
10045       case DTMF_DIGITS_SEND:
10046         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10047         {
10048           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10049             UnMapId (Id), (char   *)(FILE_), __LINE__));
10050           Info = _WRONG_MESSAGE_FORMAT;
10051           break;
10052         }
10053         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10054         {
10055           plci->dtmf_send_pulse_ms = READ_WORD (dtmf_parms[1].info);
10056           plci->dtmf_send_pause_ms = READ_WORD (dtmf_parms[2].info);
10057         }
10058         i = 0;
10059         j = 0;
10060         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10061         {
10062           j = 0;
10063           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10064             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10065              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10066           {
10067             j++;
10068           }
10069           i++;
10070         }
10071         if (j == DTMF_DIGIT_MAP_ENTRIES)
10072         {
10073           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10074             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10075           WRITE_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10076           break;
10077         }
10078         if (plci->dtmf_send_requests >=
10079           sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0]))
10080         {
10081           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10082             UnMapId (Id), (char   *)(FILE_), __LINE__));
10083           Info = _WRONG_STATE;
10084           break;
10085         }
10086         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10087         start_internal_command (Id, plci, dtmf_command);
10088         return (FALSE);
10089
10090       default:
10091         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10092           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10093         WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10094       }
10095     }
10096   }
10097   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10098     "wws", Info, SELECTOR_DTMF, result);
10099   return (FALSE);
10100 }
10101
10102
10103 static void dtmf_confirmation (dword Id, PLCI   *plci)
10104 {
10105   word Info;
10106   word i;
10107     byte result[4];
10108
10109   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10110     UnMapId (Id), (char   *)(FILE_), __LINE__));
10111
10112   Info = GOOD;
10113   result[0] = 2;
10114   WRITE_WORD (&result[1], DTMF_SUCCESS);
10115   if (plci->dtmf_send_requests != 0)
10116   {
10117     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10118       "wws", GOOD, SELECTOR_DTMF, result);
10119     (plci->dtmf_send_requests)--;
10120     for (i = 0; i < plci->dtmf_send_requests; i++)
10121       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10122   }
10123 }
10124
10125
10126 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10127 {
10128   word i, j, n;
10129
10130   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10131     UnMapId (Id), (char   *)(FILE_), __LINE__));
10132
10133   n = 0;
10134   for (i = 1; i < length; i++)
10135   {
10136     j = 0;
10137     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10138       && ((msg[i] != dtmf_digit_map[j].code)
10139        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10140     {
10141       j++;
10142     }
10143     if (j < DTMF_DIGIT_MAP_ENTRIES)
10144     {
10145
10146       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10147        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10148        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10149       {
10150         if (n + 1 == i)
10151         {
10152           for (i = length; i > n + 1; i--)
10153             msg[i] = msg[i - 1];
10154           length++;
10155           i++;
10156         }
10157         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10158       }
10159       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10160
10161       msg[++n] = dtmf_digit_map[j].character;
10162     }
10163   }
10164   if (n != 0)
10165   {
10166     msg[0] = (byte) n;
10167     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10168   }
10169 }
10170
10171
10172 /*------------------------------------------------------------------*/
10173 /* DTMF parameters                                                  */
10174 /*------------------------------------------------------------------*/
10175
10176 static void dtmf_parameter_write (PLCI   *plci)
10177 {
10178   word i;
10179     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10180
10181   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10182     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10183     (char   *)(FILE_), __LINE__));
10184
10185   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10186   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10187   for (i = 0; i < plci->dtmf_parameter_length; i++)
10188     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10189   add_p (plci, FTY, parameter_buffer);
10190   sig_req (plci, TEL_CTRL, 0);
10191   send_req (plci);
10192 }
10193
10194
10195 static void dtmf_parameter_clear_config (PLCI   *plci)
10196 {
10197
10198   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10199     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10200     (char   *)(FILE_), __LINE__));
10201
10202   plci->dtmf_parameter_length = 0;
10203 }
10204
10205
10206 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10207 {
10208
10209   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10210     UnMapId (Id), (char   *)(FILE_), __LINE__));
10211
10212 }
10213
10214
10215 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10216 {
10217
10218   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10219     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10220
10221   return (GOOD);
10222 }
10223
10224
10225 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10226 {
10227   word Info;
10228
10229   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10230     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231
10232   Info = GOOD;
10233   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10234    && (plci->dtmf_parameter_length != 0))
10235   {
10236     switch (plci->adjust_b_state)
10237     {
10238     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10239       plci->internal_command = plci->adjust_b_command;
10240       if (plci->sig_req)
10241       {
10242         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10243         break;
10244       }
10245       dtmf_parameter_write (plci);
10246       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10247       break;
10248     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10249       if ((Rc != OK) && (Rc != OK_FC))
10250       {
10251         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10252           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10253         Info = _WRONG_STATE;
10254         break;
10255       }
10256       break;
10257     }
10258   }
10259   return (Info);
10260 }
10261
10262
10263 /*------------------------------------------------------------------*/
10264 /* Line interconnect facilities                                     */
10265 /*------------------------------------------------------------------*/
10266
10267
10268 LI_CONFIG   *li_config_table = 0;
10269 word li_total_channels = 0;
10270
10271
10272 /*------------------------------------------------------------------*/
10273 /* translate a CHI information element to a channel number          */
10274 /* returns 0xff - any channel                                       */
10275 /*         0xfe - chi wrong coding                                  */
10276 /*         0xfd - D-channel                                         */
10277 /*         0x00 - no channel                                        */
10278 /*         else channel number / PRI: timeslot                      */
10279 /* if channels is provided we accept more than one channel.         */
10280 /*------------------------------------------------------------------*/
10281
10282 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10283 {
10284   int p;
10285   int i;
10286   dword map;
10287   byte excl;
10288   byte ofs;
10289   byte ch;
10290
10291   if (pchannelmap) *pchannelmap = 0;
10292   if(!chi[0]) return 0xff;
10293   excl = 0;
10294
10295   if(chi[1] & 0x20) {
10296     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10297     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10298     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10299     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10300     if(chi[1] &0x08) excl = 0x40;
10301
10302         /* int. id present */
10303     if(chi[1] &0x40) {
10304       p=i+1;
10305       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10306       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10307     }
10308
10309         /* coding standard, Number/Map, Channel Type */
10310     p=i+1;
10311     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10312     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10313     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10314
10315         /* Number/Map */
10316     if(chi[p] &0x10) {
10317
10318         /* map */
10319       if((chi[0]-p)==4) ofs = 0;
10320       else if((chi[0]-p)==3) ofs = 1;
10321       else return 0xfe;
10322       ch = 0;
10323       map = 0;
10324       for(i=0; i<4 && p<chi[0]; i++) {
10325         p++;
10326         ch += 8;
10327         map <<= 8;
10328         if(chi[p]) {
10329           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10330           map |= chi[p];
10331         }
10332       }
10333       ch += ofs;
10334       map <<= ofs;
10335     }
10336     else {
10337
10338         /* number */
10339       p=i+1;
10340       ch = chi[p] &0x3f;
10341       if(pchannelmap) {
10342         if((byte)(chi[0]-p)>30) return 0xfe;
10343         map = 0;
10344         for(i=p; i<=chi[0]; i++) {
10345           if ((chi[i] &0x7f) > 31) return 0xfe;
10346           map |= (1L << (chi[i] &0x7f));
10347         }
10348       }
10349       else {
10350         if(p!=chi[0]) return 0xfe;
10351         if (ch > 31) return 0xfe;
10352         map = (1L << ch);
10353       }
10354       if(chi[p] &0x40) return 0xfe;
10355     }
10356     if (pchannelmap) *pchannelmap = map;
10357     else if (map != ((dword)(1L << ch))) return 0xfe;
10358     return (byte)(excl | ch);
10359   }
10360   else {  /* not PRI */
10361     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10362     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10363     if(chi[1] &0x08) excl = 0x40;
10364
10365     switch(chi[1] |0x98) {
10366     case 0x98: return 0;
10367     case 0x99:
10368       if (pchannelmap) *pchannelmap = 2;
10369       return excl |1;
10370     case 0x9a:
10371       if (pchannelmap) *pchannelmap = 4;
10372       return excl |2;
10373     case 0x9b: return 0xff;
10374     case 0x9c: return 0xfd; /* d-ch */
10375     default: return 0xfe;
10376     }
10377   }
10378 }
10379
10380
10381 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10382 {
10383   DIVA_CAPI_ADAPTER   *a;
10384   PLCI   *splci;
10385   byte old_id;
10386
10387   a = plci->adapter;
10388   old_id = plci->li_bchannel_id;
10389   if (a->li_pri)
10390   {
10391     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10392       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10393     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10394     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10395       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10396   }
10397   else
10398   {
10399     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10400     {
10401       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10402         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10403       plci->li_bchannel_id = bchannel_id & 0x03;
10404       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10405       {
10406         splci = a->AdvSignalPLCI;
10407         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10408         {
10409           if ((splci->li_bchannel_id != 0)
10410            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10411           {
10412             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10413           }
10414           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10415           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10416           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10417             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10418             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10419         }
10420       }
10421       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10422         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10423     }
10424   }
10425   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10426    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10427   {
10428     mixer_clear_config (plci);
10429   }
10430   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10431     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10432     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10433 }
10434
10435
10436 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10437 {
10438   DIVA_CAPI_ADAPTER   *a;
10439   PLCI   *splci;
10440   byte ch, old_id;
10441
10442   a = plci->adapter;
10443   old_id = plci->li_bchannel_id;
10444   ch = chi_to_channel (chi, NULL);
10445   if (!(ch & 0x80))
10446   {
10447     if (a->li_pri)
10448     {
10449       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10450         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10451       plci->li_bchannel_id = (ch & 0x1f) + 1;
10452       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10453         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10454     }
10455     else
10456     {
10457       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10458       {
10459         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10460           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10461         plci->li_bchannel_id = ch & 0x1f;
10462         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10463         {
10464           splci = a->AdvSignalPLCI;
10465           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10466           {
10467             if ((splci->li_bchannel_id != 0)
10468              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10469             {
10470               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10471             }
10472             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10473             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10474             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10475               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10476               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10477           }
10478         }
10479         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10480           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10481       }
10482     }
10483   }
10484   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10485    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10486   {
10487     mixer_clear_config (plci);
10488   }
10489   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10490     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10491     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10492 }
10493
10494
10495 #define MIXER_MAX_DUMP_CHANNELS 34
10496
10497 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10498 {
10499 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10500   word n, i, j;
10501   char *p;
10502     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10503
10504   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10505     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10506
10507   for (i = 0; i < li_total_channels; i++)
10508   {
10509     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10510     if (li_config_table[i].chflags != 0)
10511       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10512     else
10513     {
10514       for (j = 0; j < li_total_channels; j++)
10515       {
10516         if (((li_config_table[i].flag_table[j]) != 0)
10517          || ((li_config_table[j].flag_table[i]) != 0))
10518         {
10519           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10520         }
10521         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10522          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10523         {
10524           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10525         }
10526       }
10527     }
10528   }
10529   for (i = 0; i < li_total_channels; i++)
10530   {
10531     for (j = 0; j < li_total_channels; j++)
10532     {
10533       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10534       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10535         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10536     }
10537   }
10538   for (n = 0; n < li_total_channels; n++)
10539   {
10540     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10541     {
10542       for (i = 0; i < li_total_channels; i++)
10543       {
10544         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10545         {
10546           for (j = 0; j < li_total_channels; j++)
10547           {
10548             li_config_table[i].coef_table[j] |=
10549               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10550           }
10551         }
10552       }
10553     }
10554   }
10555   for (i = 0; i < li_total_channels; i++)
10556   {
10557     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10558     {
10559       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10560       for (j = 0; j < li_total_channels; j++)
10561       {
10562         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10563           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10564       }
10565       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10566         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10567     }
10568   }
10569   for (i = 0; i < li_total_channels; i++)
10570   {
10571     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10572     {
10573       for (j = 0; j < li_total_channels; j++)
10574       {
10575         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10576           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10577         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10578           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10579         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10580           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10581         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10582           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10583       }
10584       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10585       {
10586         for (j = 0; j < li_total_channels; j++)
10587         {
10588           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10589           {
10590             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10591             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10592               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10593           }
10594         }
10595       }
10596       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10597       {
10598         for (j = 0; j < li_total_channels; j++)
10599         {
10600           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10601             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10602         }
10603       }
10604       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10605       {
10606         for (j = 0; j < li_total_channels; j++)
10607         {
10608           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10609           {
10610             for (n = 0; n < li_total_channels; n++)
10611             {
10612               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10613               {
10614                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10615                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10616                 {
10617                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10618                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10619                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10620                 }
10621                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10622                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10623               }
10624             }
10625           }
10626         }
10627       }
10628     }
10629   }
10630   for (i = 0; i < li_total_channels; i++)
10631   {
10632     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10633     {
10634       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10635         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10636       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10637         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10638       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10639         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10640       for (j = 0; j < li_total_channels; j++)
10641       {
10642         if ((li_config_table[i].flag_table[j] &
10643           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10644          || (li_config_table[j].flag_table[i] &
10645           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10646         {
10647           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10648         }
10649         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10650           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10651         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10652           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10653       }
10654       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10655       {
10656         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10657         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10658       }
10659     }
10660   }
10661   for (i = 0; i < li_total_channels; i++)
10662   {
10663     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10664     {
10665       j = 0;
10666       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10667         j++;
10668       if (j < li_total_channels)
10669       {
10670         for (j = 0; j < li_total_channels; j++)
10671         {
10672           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10673           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10674             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10675         }
10676       }
10677     }
10678   }
10679   n = li_total_channels;
10680   if (n > MIXER_MAX_DUMP_CHANNELS)
10681     n = MIXER_MAX_DUMP_CHANNELS;
10682   p = hex_line;
10683   for (j = 0; j < n; j++)
10684   {
10685     if ((j & 0x7) == 0)
10686       *(p++) = ' ';
10687     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10688     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10689   }
10690   *p = '\0';
10691   dbug (1, dprintf ("[%06lx] CURRENT %s",
10692     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10693   p = hex_line;
10694   for (j = 0; j < n; j++)
10695   {
10696     if ((j & 0x7) == 0)
10697       *(p++) = ' ';
10698     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10699     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10700   }
10701   *p = '\0';
10702   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10703     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10704   p = hex_line;
10705   for (j = 0; j < n; j++)
10706   {
10707     if ((j & 0x7) == 0)
10708       *(p++) = ' ';
10709     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10710     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10711   }
10712   *p = '\0';
10713   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10714     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10715   for (i = 0; i < n; i++)
10716   {
10717     p = hex_line;
10718     for (j = 0; j < n; j++)
10719     {
10720       if ((j & 0x7) == 0)
10721         *(p++) = ' ';
10722       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10723       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10724     }
10725     *p = '\0';
10726     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10727       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10728   }
10729   for (i = 0; i < n; i++)
10730   {
10731     p = hex_line;
10732     for (j = 0; j < n; j++)
10733     {
10734       if ((j & 0x7) == 0)
10735         *(p++) = ' ';
10736       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10737       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10738     }
10739     *p = '\0';
10740     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10741       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10742   }
10743 }
10744
10745
10746 static struct
10747 {
10748   byte mask;
10749   byte line_flags;
10750 } mixer_write_prog_pri[] =
10751 {
10752   { LI_COEF_CH_CH, 0 },
10753   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10754   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10755   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10756 };
10757
10758 static struct
10759 {
10760   byte from_ch;
10761   byte to_ch;
10762   byte mask;
10763   byte xconnect_override;
10764 } mixer_write_prog_bri[] =
10765 {
10766   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10767   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10768   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10769   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10770   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10771   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10772   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10773   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10774   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10775   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10776   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10777   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10778   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10779   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10780   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10781   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10782   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10783   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10784   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10785   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10786   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10787   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10788   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10789   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10790   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10791   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10792   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10793   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10794   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10795   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10796   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10797   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10798   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10799   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10800   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10801   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10802 };
10803
10804 static byte mixer_swapped_index_bri[] =
10805 {
10806   18,  /* B      to B      */
10807   19,  /* Alt B  to B      */
10808   20,  /* PC     to B      */
10809   21,  /* Alt PC to B      */
10810   22,  /* IC     to B      */
10811   23,  /* Alt IC to B      */
10812   24,  /* B      to PC     */
10813   25,  /* Alt B  to PC     */
10814   26,  /* PC     to PC     */
10815   27,  /* Alt PC to PC     */
10816   28,  /* IC     to PC     */
10817   29,  /* Alt IC to PC     */
10818   30,  /* B      to IC     */
10819   31,  /* Alt B  to IC     */
10820   32,  /* PC     to IC     */
10821   33,  /* Alt PC to IC     */
10822   34,  /* IC     to IC     */
10823   35,  /* Alt IC to IC     */
10824   0,   /* Alt B  to Alt B  */
10825   1,   /* B      to Alt B  */
10826   2,   /* Alt PC to Alt B  */
10827   3,   /* PC     to Alt B  */
10828   4,   /* Alt IC to Alt B  */
10829   5,   /* IC     to Alt B  */
10830   6,   /* Alt B  to Alt PC */
10831   7,   /* B      to Alt PC */
10832   8,   /* Alt PC to Alt PC */
10833   9,   /* PC     to Alt PC */
10834   10,  /* Alt IC to Alt PC */
10835   11,  /* IC     to Alt PC */
10836   12,  /* Alt B  to Alt IC */
10837   13,  /* B      to Alt IC */
10838   14,  /* Alt PC to Alt IC */
10839   15,  /* PC     to Alt IC */
10840   16,  /* Alt IC to Alt IC */
10841   17   /* IC     to Alt IC */
10842 };
10843
10844 static struct
10845 {
10846   byte mask;
10847   byte from_pc;
10848   byte to_pc;
10849 } xconnect_write_prog[] =
10850 {
10851   { LI_COEF_CH_CH, FALSE, FALSE },
10852   { LI_COEF_CH_PC, FALSE, TRUE },
10853   { LI_COEF_PC_CH, TRUE, FALSE },
10854   { LI_COEF_PC_PC, TRUE, TRUE }
10855 };
10856
10857
10858 static void xconnect_query_addresses (PLCI   *plci)
10859 {
10860   DIVA_CAPI_ADAPTER   *a;
10861   word w, ch;
10862   byte   *p;
10863
10864   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10865     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10866     (char   *)(FILE_), __LINE__));
10867
10868   a = plci->adapter;
10869   if (a->li_pri && ((plci->li_bchannel_id == 0)
10870    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10871   {
10872     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10873       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10874       (char   *)(FILE_), __LINE__));
10875     return;
10876   }
10877   p = plci->internal_req_buffer;
10878   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10879   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10880   w = ch;
10881   *(p++) = (byte) w;
10882   *(p++) = (byte)(w >> 8);
10883   w = ch | XCONNECT_CHANNEL_PORT_PC;
10884   *(p++) = (byte) w;
10885   *(p++) = (byte)(w >> 8);
10886   plci->NData[0].P = plci->internal_req_buffer;
10887   plci->NData[0].PLength = p - plci->internal_req_buffer;
10888   plci->NL.X = plci->NData;
10889   plci->NL.ReqCh = 0;
10890   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10891   plci->adapter->request (&plci->NL);
10892 }
10893
10894
10895 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10896 {
10897
10898   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10899     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10900     (char   *)(FILE_), __LINE__, internal_command));
10901
10902   plci->li_write_command = internal_command;
10903   plci->li_write_channel = 0;
10904 }
10905
10906
10907 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10908 {
10909   DIVA_CAPI_ADAPTER   *a;
10910   word w, n, i, j, r, s, to_ch;
10911   dword d;
10912   byte   *p;
10913   struct xconnect_transfer_address_s   *transfer_address;
10914   byte ch_map[MIXER_CHANNELS_BRI];
10915
10916   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10917     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10918
10919   a = plci->adapter;
10920   if ((plci->li_bchannel_id == 0)
10921    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10922   {
10923     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10924       UnMapId (Id), (char   *)(FILE_), __LINE__));
10925     return (TRUE);
10926   }
10927   i = a->li_base + (plci->li_bchannel_id - 1);
10928   j = plci->li_write_channel;
10929   p = plci->internal_req_buffer;
10930   if (j != 0)
10931   {
10932     if ((Rc != OK) && (Rc != OK_FC))
10933     {
10934       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10935         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10936       return (FALSE);
10937     }
10938   }
10939   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10940   {
10941     r = 0;
10942     s = 0;
10943     if (j < li_total_channels)
10944     {
10945       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10946       {
10947         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10948             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10949           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10950             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10951       }
10952       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10953       while ((j < li_total_channels)
10954         && ((r == 0)
10955          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10956          || (!li_config_table[j].adapter->li_pri
10957           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10958          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10959            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10960           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10961            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10962          || ((li_config_table[j].adapter->li_base != a->li_base)
10963           && !(r & s &
10964             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10965               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10966             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10967               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10968       {
10969         j++;
10970         if (j < li_total_channels)
10971           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10972       }
10973     }
10974     if (j < li_total_channels)
10975     {
10976       plci->internal_command = plci->li_write_command;
10977       if (plci_nl_busy (plci))
10978         return (TRUE);
10979       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10980       *(p++) = UDATA_REQUEST_XCONNECT_TO;
10981       do
10982       {
10983         if (li_config_table[j].adapter->li_base != a->li_base)
10984         {
10985           r &= s &
10986             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10987               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10988             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10989               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10990         }
10991         n = 0;
10992         do
10993         {
10994           if (r & xconnect_write_prog[n].mask)
10995           {
10996             if (xconnect_write_prog[n].from_pc)
10997               transfer_address = &(li_config_table[j].send_pc);
10998             else
10999               transfer_address = &(li_config_table[j].send_b);
11000             d = transfer_address->card_address.low;
11001             *(p++) = (byte) d;
11002             *(p++) = (byte)(d >> 8);
11003             *(p++) = (byte)(d >> 16);
11004             *(p++) = (byte)(d >> 24);
11005             d = transfer_address->card_address.high;
11006             *(p++) = (byte) d;
11007             *(p++) = (byte)(d >> 8);
11008             *(p++) = (byte)(d >> 16);
11009             *(p++) = (byte)(d >> 24);
11010             d = transfer_address->offset;
11011             *(p++) = (byte) d;
11012             *(p++) = (byte)(d >> 8);
11013             *(p++) = (byte)(d >> 16);
11014             *(p++) = (byte)(d >> 24);
11015             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11016             *(p++) = (byte) w;
11017             *(p++) = (byte)(w >> 8);
11018             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11019               (li_config_table[i].adapter->u_law ?
11020                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11021                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11022             *(p++) = (byte) w;
11023             *(p++) = (byte) 0;
11024             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11025           }
11026           n++;
11027         } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11028           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11029         if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11030         {
11031           do
11032           {
11033             j++;
11034             if (j < li_total_channels)
11035               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11036           } while ((j < li_total_channels)
11037             && ((r == 0)
11038              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11039              || (!li_config_table[j].adapter->li_pri
11040               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11041              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11042                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11043               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11044                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11045              || ((li_config_table[j].adapter->li_base != a->li_base)
11046               && !(r & s &
11047                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11048                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11049                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11050                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11051         }
11052       } while ((j < li_total_channels)
11053         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11054     }
11055     else if (j == li_total_channels)
11056     {
11057       plci->internal_command = plci->li_write_command;
11058       if (plci_nl_busy (plci))
11059         return (TRUE);
11060       if (a->li_pri)
11061       {
11062         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11063         w = 0;
11064         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11065           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11066         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11067           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11068         *(p++) = (byte) w;
11069         *(p++) = (byte)(w >> 8);
11070       }
11071       else
11072       {
11073         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11074         w = 0;
11075         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11076          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11077         {
11078           w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11079         }
11080         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11081           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11082         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11083           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11084         *(p++) = (byte) w;
11085         *(p++) = (byte)(w >> 8);
11086         for (j = 0; j < sizeof(ch_map); j += 2)
11087         {
11088           if (plci->li_bchannel_id == 2)
11089           {
11090             ch_map[j] = (byte)(j+1);
11091             ch_map[j+1] = (byte) j;
11092           }
11093           else
11094           {
11095             ch_map[j] = (byte) j;
11096             ch_map[j+1] = (byte)(j+1);
11097           }
11098         }
11099         for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11100         {
11101           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11102           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11103           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11104           {
11105             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11106               mixer_write_prog_bri[n].xconnect_override :
11107               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11108             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11109             {
11110               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11111               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11112             }
11113           }
11114           else
11115           {
11116             *p = 0x00;
11117             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11118             {
11119               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11120               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11121                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11122             }
11123           }
11124           p++;
11125         }
11126       }
11127       j = li_total_channels + 1;
11128     }
11129   }
11130   else
11131   {
11132     if (j <= li_total_channels)
11133     {
11134       plci->internal_command = plci->li_write_command;
11135       if (plci_nl_busy (plci))
11136         return (TRUE);
11137       if (j < a->li_base)
11138         j = a->li_base;
11139       if (a->li_pri)
11140       {
11141         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11142         w = 0;
11143         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11144           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11145         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11146           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11147         *(p++) = (byte) w;
11148         *(p++) = (byte)(w >> 8);
11149         for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++)
11150         {
11151           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11152           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11153           {
11154             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11155             if (w & mixer_write_prog_pri[n].mask)
11156             {
11157               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11158               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11159             }
11160             else
11161               *(p++) = 0x00;
11162           }
11163           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11164           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11165           {
11166             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11167             if (w & mixer_write_prog_pri[n].mask)
11168             {
11169               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11170               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11171             }
11172             else
11173               *(p++) = 0x00;
11174           }
11175         }
11176       }
11177       else
11178       {
11179         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11180         w = 0;
11181         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11182          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11183         {
11184           w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11185         }
11186         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11187           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11188         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11189           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11190         *(p++) = (byte) w;
11191         *(p++) = (byte)(w >> 8);
11192         for (j = 0; j < sizeof(ch_map); j += 2)
11193         {
11194           if (plci->li_bchannel_id == 2)
11195           {
11196             ch_map[j] = (byte)(j+1);
11197             ch_map[j+1] = (byte) j;
11198           }
11199           else
11200           {
11201             ch_map[j] = (byte) j;
11202             ch_map[j+1] = (byte)(j+1);
11203           }
11204         }
11205         for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11206         {
11207           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11208           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11209           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11210           {
11211             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11212             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11213             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11214           }
11215           else
11216           {
11217             *p = 0x00;
11218             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11219             {
11220               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11221               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11222                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11223             }
11224           }
11225           p++;
11226         }
11227       }
11228       j = li_total_channels + 1;
11229     }
11230   }
11231   plci->li_write_channel = j;
11232   if (p != plci->internal_req_buffer)
11233   {
11234     plci->NData[0].P = plci->internal_req_buffer;
11235     plci->NData[0].PLength = p - plci->internal_req_buffer;
11236     plci->NL.X = plci->NData;
11237     plci->NL.ReqCh = 0;
11238     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11239     plci->adapter->request (&plci->NL);
11240   }
11241   return (TRUE);
11242 }
11243
11244
11245 static void mixer_notify_update (PLCI   *plci, byte others)
11246 {
11247   DIVA_CAPI_ADAPTER   *a;
11248   word i, w;
11249   PLCI   *notify_plci;
11250     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11251
11252   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11253     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11254     (char   *)(FILE_), __LINE__, others));
11255
11256   a = plci->adapter;
11257   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11258   {
11259     if (others)
11260       plci->li_notify_update = TRUE;
11261     i = 0;
11262     do
11263     {
11264       notify_plci = NULL;
11265       if (others)
11266       {
11267         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11268           i++;
11269         if (i < li_total_channels)
11270           notify_plci = li_config_table[i++].plci;
11271       }
11272       else
11273       {
11274         if ((plci->li_bchannel_id != 0)
11275          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11276         {
11277           notify_plci = plci;
11278         }
11279       }
11280       if ((notify_plci != NULL)
11281        && !notify_plci->li_notify_update
11282        && (notify_plci->appl != NULL)
11283        && (notify_plci->State)
11284        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11285       {
11286         notify_plci->li_notify_update = TRUE;
11287         ((CAPI_MSG *) msg)->header.length = 18;
11288         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11289         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11290         ((CAPI_MSG *) msg)->header.number = 0;
11291         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11292         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11293         ((CAPI_MSG *) msg)->header.ncci = 0;
11294         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11295         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11296         WRITE_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11297         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11298         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11299         if (w != _QUEUE_FULL)
11300         {
11301           if (w != 0)
11302           {
11303             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11304               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11305               (char   *)(FILE_), __LINE__,
11306               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11307           }
11308           notify_plci->li_notify_update = FALSE;
11309         }
11310       }
11311     } while (others && (notify_plci != NULL));
11312     if (others)
11313       plci->li_notify_update = FALSE;
11314   }
11315 }
11316
11317
11318 static void mixer_clear_config (PLCI   *plci)
11319 {
11320   DIVA_CAPI_ADAPTER   *a;
11321   word i, j;
11322
11323   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11324     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11325     (char   *)(FILE_), __LINE__));
11326
11327   plci->li_notify_update = FALSE;
11328   plci->li_plci_b_write_pos = 0;
11329   plci->li_plci_b_read_pos = 0;
11330   plci->li_plci_b_req_pos = 0;
11331   a = plci->adapter;
11332   if ((plci->li_bchannel_id != 0)
11333    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11334   {
11335     i = a->li_base + (plci->li_bchannel_id - 1);
11336     li_config_table[i].curchnl = 0;
11337     li_config_table[i].channel = 0;
11338     li_config_table[i].chflags = 0;
11339     for (j = 0; j < li_total_channels; j++)
11340     {
11341       li_config_table[j].flag_table[i] = 0;
11342       li_config_table[i].flag_table[j] = 0;
11343       li_config_table[i].coef_table[j] = 0;
11344       li_config_table[j].coef_table[i] = 0;
11345     }
11346     if (!a->li_pri)
11347     {
11348       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11349       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11350       {
11351         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11352         li_config_table[i].curchnl = 0;
11353         li_config_table[i].channel = 0;
11354         li_config_table[i].chflags = 0;
11355         for (j = 0; j < li_total_channels; j++)
11356         {
11357           li_config_table[i].flag_table[j] = 0;
11358           li_config_table[j].flag_table[i] = 0;
11359           li_config_table[i].coef_table[j] = 0;
11360           li_config_table[j].coef_table[i] = 0;
11361         }
11362         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11363         {
11364           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11365           li_config_table[i].curchnl = 0;
11366           li_config_table[i].channel = 0;
11367           li_config_table[i].chflags = 0;
11368           for (j = 0; j < li_total_channels; j++)
11369           {
11370             li_config_table[i].flag_table[j] = 0;
11371             li_config_table[j].flag_table[i] = 0;
11372             li_config_table[i].coef_table[j] = 0;
11373             li_config_table[j].coef_table[i] = 0;
11374           }
11375         }
11376       }
11377     }
11378   }
11379 }
11380
11381
11382 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11383 {
11384
11385   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11386     UnMapId (Id), (char   *)(FILE_), __LINE__));
11387
11388   do
11389   {
11390     mixer_indication_coefs_set (Id, plci);
11391   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11392 }
11393
11394
11395 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11396 {
11397   DIVA_CAPI_ADAPTER   *a;
11398   word i, j;
11399
11400   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11401     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11402
11403   a = plci->adapter;
11404   if ((plci->li_bchannel_id != 0)
11405    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11406   {
11407     i = a->li_base + (plci->li_bchannel_id - 1);
11408     for (j = 0; j < li_total_channels; j++)
11409     {
11410       li_config_table[i].coef_table[j] &= 0xf;
11411       li_config_table[j].coef_table[i] &= 0xf;
11412     }
11413     if (!a->li_pri)
11414       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11415   }
11416   return (GOOD);
11417 }
11418
11419
11420 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11421 {
11422   DIVA_CAPI_ADAPTER   *a;
11423   word Info;
11424
11425   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11426     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11427
11428   Info = GOOD;
11429   a = plci->adapter;
11430   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11431    && (plci->li_bchannel_id != 0)
11432    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11433   {
11434     switch (plci->adjust_b_state)
11435     {
11436     case ADJUST_B_RESTORE_MIXER_1:
11437       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11438       {
11439         plci->internal_command = plci->adjust_b_command;
11440         if (plci_nl_busy (plci))
11441         {
11442           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11443           break;
11444         }
11445         xconnect_query_addresses (plci);
11446         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11447         break;
11448       }
11449       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11450       Rc = OK;
11451     case ADJUST_B_RESTORE_MIXER_2:
11452     case ADJUST_B_RESTORE_MIXER_3:
11453     case ADJUST_B_RESTORE_MIXER_4:
11454       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11455       {
11456         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11457           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11458         Info = _WRONG_STATE;
11459         break;
11460       }
11461       if (Rc == OK)
11462       {
11463         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11464           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11465         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11466           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11467       }
11468       else if (Rc == 0)
11469       {
11470         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11471           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11472         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11473           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11474       }
11475       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11476       {
11477         plci->internal_command = plci->adjust_b_command;
11478         break;
11479       }
11480     case ADJUST_B_RESTORE_MIXER_5:
11481       xconnect_write_coefs (plci, plci->adjust_b_command);
11482       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11483       Rc = OK;
11484     case ADJUST_B_RESTORE_MIXER_6:
11485       if (!xconnect_write_coefs_process (Id, plci, Rc))
11486       {
11487         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11488           UnMapId (Id), (char   *)(FILE_), __LINE__));
11489         Info = _FACILITY_NOT_SUPPORTED;
11490         break;
11491       }
11492       if (plci->internal_command)
11493         break;
11494       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11495     case ADJUST_B_RESTORE_MIXER_7:
11496       break;
11497     }
11498   }
11499   return (Info);
11500 }
11501
11502
11503 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11504 {
11505   DIVA_CAPI_ADAPTER   *a;
11506   word i, internal_command, Info;
11507
11508   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11509     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11510     plci->li_cmd));
11511
11512   Info = GOOD;
11513   a = plci->adapter;
11514   internal_command = plci->internal_command;
11515   plci->internal_command = 0;
11516   switch (plci->li_cmd)
11517   {
11518   case LI_REQ_CONNECT:
11519   case LI_REQ_DISCONNECT:
11520   case LI_REQ_SILENT_UPDATE:
11521     switch (internal_command)
11522     {
11523     default:
11524       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11525       {
11526         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11527           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11528       }
11529     case MIXER_COMMAND_1:
11530       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11531       {
11532         if (adjust_b_process (Id, plci, Rc) != GOOD)
11533         {
11534           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11535             UnMapId (Id), (char   *)(FILE_), __LINE__));
11536           Info = _FACILITY_NOT_SUPPORTED;
11537           break;
11538         }
11539         if (plci->internal_command)
11540           return;
11541       }
11542       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11543       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11544        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11545         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11546          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11547       {
11548         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11549       }
11550       else
11551       {
11552         do
11553         {
11554           mixer_indication_coefs_set (Id, plci);
11555         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11556       }
11557     case MIXER_COMMAND_2:
11558       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11559        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11560         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11561          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11562       {
11563         if (!xconnect_write_coefs_process (Id, plci, Rc))
11564         {
11565           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11566             UnMapId (Id), (char   *)(FILE_), __LINE__));
11567           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11568           {
11569             do
11570             {
11571               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11572                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11573               i = (plci->li_plci_b_write_pos == 0) ?
11574                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11575             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11576               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11577           }
11578           Info = _FACILITY_NOT_SUPPORTED;
11579           break;
11580         }
11581         if (plci->internal_command)
11582           return;
11583       }
11584       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11585       {
11586         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11587           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11588       }
11589     case MIXER_COMMAND_3:
11590       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11591       {
11592         if (adjust_b_process (Id, plci, Rc) != GOOD)
11593         {
11594           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11595             UnMapId (Id), (char   *)(FILE_), __LINE__));
11596           Info = _FACILITY_NOT_SUPPORTED;
11597           break;
11598         }
11599         if (plci->internal_command)
11600           return;
11601       }
11602       break;
11603     }
11604     break;
11605   }
11606   if ((plci->li_bchannel_id == 0)
11607    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11608   {
11609     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11610       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11611   }
11612   else
11613   {
11614     i = a->li_base + (plci->li_bchannel_id - 1);
11615     li_config_table[i].curchnl = plci->li_channel_bits;
11616     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11617     {
11618       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11619       li_config_table[i].curchnl = plci->li_channel_bits;
11620       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11621       {
11622         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11623         li_config_table[i].curchnl = plci->li_channel_bits;
11624       }
11625     }
11626   }
11627 }
11628
11629
11630 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11631   dword plci_b_id, byte connect, dword li_flags)
11632 {
11633   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11634   PLCI   *plci_b;
11635   DIVA_CAPI_ADAPTER   *a_b;
11636
11637   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11638   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11639   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11640   if (!a->li_pri && (plci->tel == ADV_VOICE)
11641    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11642   {
11643     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11644     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11645       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11646   }
11647   else
11648   {
11649     ch_a_v = ch_a;
11650     ch_a_s = ch_a;
11651   }
11652   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11653   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11654    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11655   {
11656     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11657     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11658       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11659   }
11660   else
11661   {
11662     ch_b_v = ch_b;
11663     ch_b_s = ch_b;
11664   }
11665   if (connect)
11666   {
11667     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11668     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11669     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11671   }
11672   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11673   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11674   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11675   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11676   if (ch_a_v == ch_b_v)
11677   {
11678     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11679     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11680   }
11681   else
11682   {
11683     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11684     {
11685       for (i = 0; i < li_total_channels; i++)
11686       {
11687         if (i != ch_a_v)
11688           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11689       }
11690     }
11691     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11692     {
11693       for (i = 0; i < li_total_channels; i++)
11694       {
11695         if (i != ch_a_s)
11696           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11697       }
11698     }
11699     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11700     {
11701       for (i = 0; i < li_total_channels; i++)
11702       {
11703         if (i != ch_a_v)
11704           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11705       }
11706     }
11707     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11708     {
11709       for (i = 0; i < li_total_channels; i++)
11710       {
11711         if (i != ch_a_s)
11712           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11713       }
11714     }
11715   }
11716   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11717   {
11718     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11719     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11720     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11721     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11722   }
11723   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11724   {
11725     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11726     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11727     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11728     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11729   }
11730   if (li_flags & LI_FLAG_MONITOR_A)
11731   {
11732     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11733     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11734   }
11735   if (li_flags & LI_FLAG_MONITOR_B)
11736   {
11737     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11738     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11739   }
11740   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11741   {
11742     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11744   }
11745   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11746   {
11747     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11748     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11749   }
11750   if (li_flags & LI_FLAG_MIX_A)
11751   {
11752     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11753     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11754   }
11755   if (li_flags & LI_FLAG_MIX_B)
11756   {
11757     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11758     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11759   }
11760   if (ch_a_v != ch_a_s)
11761   {
11762     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11763     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11764   }
11765   if (ch_b_v != ch_b_s)
11766   {
11767     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11768     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11769   }
11770 }
11771
11772
11773 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11774   dword plci_b_id, byte connect, dword li_flags)
11775 {
11776   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11777   PLCI   *plci_b;
11778   DIVA_CAPI_ADAPTER   *a_b;
11779
11780   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11781   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11782   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11783   if (!a->li_pri && (plci->tel == ADV_VOICE)
11784    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11785   {
11786     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11787     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11788       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11789   }
11790   else
11791   {
11792     ch_a_v = ch_a;
11793     ch_a_s = ch_a;
11794   }
11795   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11796   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11797    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11798   {
11799     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11800     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11801       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11802   }
11803   else
11804   {
11805     ch_b_v = ch_b;
11806     ch_b_s = ch_b;
11807   }
11808   if (connect)
11809   {
11810     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11811     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11812     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11813     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11814     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11815     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11816   }
11817   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11826   {
11827     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11828     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11829     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11830     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11831   }
11832   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11833   {
11834     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11835     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11836     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11837     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11838   }
11839   if (li_flags & LI2_FLAG_MONITOR_B)
11840   {
11841     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11842     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11843   }
11844   if (li_flags & LI2_FLAG_MIX_B)
11845   {
11846     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11847     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11848   }
11849   if (li_flags & LI2_FLAG_MONITOR_X)
11850     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11851   if (li_flags & LI2_FLAG_MIX_X)
11852     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11853   if (li_flags & LI2_FLAG_LOOP_B)
11854   {
11855     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11856     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11858     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11859   }
11860   if (li_flags & LI2_FLAG_LOOP_PC)
11861     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11862   if (li_flags & LI2_FLAG_LOOP_X)
11863     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11864   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11865     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11866   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11867     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11868   if (ch_a_v != ch_a_s)
11869   {
11870     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11871     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11872   }
11873   if (ch_b_v != ch_b_s)
11874   {
11875     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11876     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11877   }
11878 }
11879
11880
11881 static word li_check_main_plci (dword Id, PLCI   *plci)
11882 {
11883   if (plci == NULL)
11884   {
11885     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11886       UnMapId (Id), (char   *)(FILE_), __LINE__));
11887     return (_WRONG_IDENTIFIER);
11888   }
11889   if (!plci->State
11890    || !plci->NL.Id || plci->nl_remove_id
11891    || (plci->li_bchannel_id == 0))
11892   {
11893     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11894       UnMapId (Id), (char   *)(FILE_), __LINE__));
11895     return (_WRONG_STATE);
11896   }
11897   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11898   return (GOOD);
11899 }
11900
11901
11902 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11903   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11904 {
11905   byte ctlr_b;
11906   PLCI   *plci_b;
11907
11908   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11909     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11910   {
11911     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11912       UnMapId (Id), (char   *)(FILE_), __LINE__));
11913     WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11914     return (NULL);
11915   }
11916   ctlr_b = 0;
11917   if ((plci_b_id & 0x7f) != 0)
11918   {
11919     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11920     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11921       ctlr_b = 0;
11922   }
11923   if ((ctlr_b == 0)
11924    || (((plci_b_id >> 8) & 0xff) == 0)
11925    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11926   {
11927     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11928       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11929     WRITE_WORD (p_result, _WRONG_IDENTIFIER);
11930     return (NULL);
11931   }
11932   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11933   if (!plci_b->State
11934    || !plci_b->NL.Id || plci_b->nl_remove_id
11935    || (plci_b->li_bchannel_id == 0))
11936   {
11937     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11938       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11939     WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11940     return (NULL);
11941   }
11942   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11943   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11944     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11945    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11947   {
11948     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11949       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11950     WRITE_WORD (p_result, _WRONG_IDENTIFIER);
11951     return (NULL);
11952   }
11953   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11954     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11955   {
11956     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11957       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11958     WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11959     return (NULL);
11960   }
11961   return (plci_b);
11962 }
11963
11964
11965 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11966   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11967 {
11968   byte ctlr_b;
11969   PLCI   *plci_b;
11970
11971   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11972     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11973   {
11974     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11975       UnMapId (Id), (char   *)(FILE_), __LINE__));
11976     WRITE_WORD (p_result, _WRONG_STATE);
11977     return (NULL);
11978   }
11979   ctlr_b = 0;
11980   if ((plci_b_id & 0x7f) != 0)
11981   {
11982     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11983     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11984       ctlr_b = 0;
11985   }
11986   if ((ctlr_b == 0)
11987    || (((plci_b_id >> 8) & 0xff) == 0)
11988    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11989   {
11990     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11991       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11992     WRITE_WORD (p_result, _WRONG_IDENTIFIER);
11993     return (NULL);
11994   }
11995   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11996   if (!plci_b->State
11997    || !plci_b->NL.Id || plci_b->nl_remove_id
11998    || (plci_b->li_bchannel_id == 0)
11999    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12000   {
12001     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12002       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12003     WRITE_WORD (p_result, _WRONG_STATE);
12004     return (NULL);
12005   }
12006   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12007     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12008    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12009     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12010   {
12011     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12012       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12013     WRITE_WORD (p_result, _WRONG_IDENTIFIER);
12014     return (NULL);
12015   }
12016   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12017     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12018   {
12019     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12020       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12021     WRITE_WORD (p_result, _WRONG_STATE);
12022     return (NULL);
12023   }
12024   return (plci_b);
12025 }
12026
12027
12028 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12029 {
12030   word Info;
12031   word i;
12032   dword d, li_flags, plci_b_id;
12033   PLCI   *plci_b;
12034     API_PARSE li_parms[3];
12035     API_PARSE li_req_parms[3];
12036     API_PARSE li_participant_struct[2];
12037     API_PARSE li_participant_parms[3];
12038   word participant_parms_pos;
12039   byte result_buffer[32];
12040   byte   *result;
12041   word result_pos;
12042   word plci_b_write_pos;
12043
12044   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12045     UnMapId (Id), (char   *)(FILE_), __LINE__));
12046
12047   Info = GOOD;
12048   result = result_buffer;
12049   result_buffer[0] = 0;
12050   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12051   {
12052     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12053       UnMapId (Id), (char   *)(FILE_), __LINE__));
12054     Info = _FACILITY_NOT_SUPPORTED;
12055   }
12056   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12057   {
12058     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12059       UnMapId (Id), (char   *)(FILE_), __LINE__));
12060     Info = _WRONG_MESSAGE_FORMAT;
12061   }
12062   else
12063   {
12064     result_buffer[0] = 3;
12065     WRITE_WORD (&result_buffer[1], READ_WORD (li_parms[0].info));
12066     result_buffer[3] = 0;
12067     switch (READ_WORD (li_parms[0].info))
12068     {
12069     case LI_GET_SUPPORTED_SERVICES:
12070       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12071       {
12072         result_buffer[0] = 17;
12073         result_buffer[3] = 14;
12074         WRITE_WORD (&result_buffer[4], GOOD);
12075         d = 0;
12076         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12077           d |= LI_CONFERENCING_SUPPORTED;
12078         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12079           d |= LI_MONITORING_SUPPORTED;
12080         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12081           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12082         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12083           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12084         WRITE_DWORD (&result_buffer[6], d);
12085         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12086         {
12087           d = 0;
12088           for (i = 0; i < li_total_channels; i++)
12089           {
12090             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091              && (li_config_table[i].adapter->li_pri
12092               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12093             {
12094               d++;
12095             }
12096           }
12097         }
12098         else
12099         {
12100           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12101         }
12102         WRITE_DWORD (&result_buffer[10], d / 2);
12103         WRITE_DWORD (&result_buffer[14], d);
12104       }
12105       else
12106       {
12107         result_buffer[0] = 25;
12108         result_buffer[3] = 22;
12109         WRITE_WORD (&result_buffer[4], GOOD);
12110         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12111         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12112           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12113         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12114           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12115         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12116           d |= LI2_PC_LOOPING_SUPPORTED;
12117         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12119         WRITE_DWORD (&result_buffer[6], d);
12120         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12121         WRITE_DWORD (&result_buffer[10], d / 2);
12122         WRITE_DWORD (&result_buffer[14], d - 1);
12123         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12124         {
12125           d = 0;
12126           for (i = 0; i < li_total_channels; i++)
12127           {
12128             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12129              && (li_config_table[i].adapter->li_pri
12130               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12131             {
12132               d++;
12133             }
12134           }
12135         }
12136         WRITE_DWORD (&result_buffer[18], d / 2);
12137         WRITE_DWORD (&result_buffer[22], d - 1);
12138       }
12139       break;
12140
12141     case LI_REQ_CONNECT:
12142       if (li_parms[1].length == 8)
12143       {
12144         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12145         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12146         {
12147           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12148             UnMapId (Id), (char   *)(FILE_), __LINE__));
12149           Info = _WRONG_MESSAGE_FORMAT;
12150           break;
12151         }
12152         plci_b_id = READ_DWORD (li_req_parms[0].info) & 0xffff;
12153         li_flags = READ_DWORD (li_req_parms[1].info);
12154         Info = li_check_main_plci (Id, plci);
12155         result_buffer[0] = 9;
12156         result_buffer[3] = 6;
12157         WRITE_DWORD (&result_buffer[4], plci_b_id);
12158         WRITE_WORD (&result_buffer[8], GOOD);
12159         if (Info != GOOD)
12160           break;
12161         result = plci->saved_msg.info;
12162         for (i = 0; i <= result_buffer[0]; i++)
12163           result[i] = result_buffer[i];
12164         plci_b_write_pos = plci->li_plci_b_write_pos;
12165         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12166         if (plci_b == NULL)
12167           break;
12168         li_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12169         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12170         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12171         plci->li_plci_b_write_pos = plci_b_write_pos;
12172       }
12173       else
12174       {
12175         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12176         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12177         {
12178           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12179             UnMapId (Id), (char   *)(FILE_), __LINE__));
12180           Info = _WRONG_MESSAGE_FORMAT;
12181           break;
12182         }
12183         li_flags = READ_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12184         Info = li_check_main_plci (Id, plci);
12185         result_buffer[0] = 7;
12186         result_buffer[3] = 4;
12187         WRITE_WORD (&result_buffer[4], Info);
12188         result_buffer[6] = 0;
12189         if (Info != GOOD)
12190           break;
12191         result = plci->saved_msg.info;
12192         for (i = 0; i <= result_buffer[0]; i++)
12193           result[i] = result_buffer[i];
12194         plci_b_write_pos = plci->li_plci_b_write_pos;
12195         participant_parms_pos = 0;
12196         result_pos = 7;
12197         li2_update_connect (Id, a, plci, UnMapId (Id), TRUE, li_flags);
12198         while (participant_parms_pos < li_req_parms[1].length)
12199         {
12200           result[result_pos] = 6;
12201           result_pos += 7;
12202           WRITE_DWORD (&result[result_pos - 6], 0);
12203           WRITE_WORD (&result[result_pos - 2], GOOD);
12204           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12205             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12206           {
12207             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12208               UnMapId (Id), (char   *)(FILE_), __LINE__));
12209             WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210             break;
12211           }
12212           if (api_parse (&li_participant_struct[0].info[1],
12213             li_participant_struct[0].length, "dd", li_participant_parms))
12214           {
12215             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12216               UnMapId (Id), (char   *)(FILE_), __LINE__));
12217             WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218             break;
12219           }
12220           plci_b_id = READ_DWORD (li_participant_parms[0].info) & 0xffff;
12221           li_flags = READ_DWORD (li_participant_parms[1].info);
12222           WRITE_DWORD (&result[result_pos - 6], plci_b_id);
12223           if (sizeof(result) - result_pos < 7)
12224           {
12225             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12226               UnMapId (Id), (char   *)(FILE_), __LINE__));
12227             WRITE_WORD (&result[result_pos - 2], _WRONG_STATE);
12228             break;
12229           }
12230           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12231           if (plci_b != NULL)
12232           {
12233             li2_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12234             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12235               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12236               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12237             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12238           }
12239           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12240             (&li_req_parms[1].info[1]));
12241         }
12242         result[0] = (byte)(result_pos - 1);
12243         result[3] = (byte)(result_pos - 4);
12244         result[6] = (byte)(result_pos - 7);
12245         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12246         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12247          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12248         {
12249           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12250           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12251         }
12252         else
12253           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12254         plci->li_plci_b_write_pos = plci_b_write_pos;
12255       }
12256       mixer_calculate_coefs (a);
12257       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12258       mixer_notify_update (plci, TRUE);
12259       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12260         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12261       plci->command = 0;
12262       plci->li_cmd = READ_WORD (li_parms[0].info);
12263       start_internal_command (Id, plci, mixer_command);
12264       return (FALSE);
12265
12266     case LI_REQ_DISCONNECT:
12267       if (li_parms[1].length == 4)
12268       {
12269         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12270         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12271         {
12272           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12273             UnMapId (Id), (char   *)(FILE_), __LINE__));
12274           Info = _WRONG_MESSAGE_FORMAT;
12275           break;
12276         }
12277         plci_b_id = READ_DWORD (li_req_parms[0].info) & 0xffff;
12278         Info = li_check_main_plci (Id, plci);
12279         result_buffer[0] = 9;
12280         result_buffer[3] = 6;
12281         WRITE_DWORD (&result_buffer[4], READ_DWORD (li_req_parms[0].info));
12282         WRITE_WORD (&result_buffer[8], GOOD);
12283         if (Info != GOOD)
12284           break;
12285         result = plci->saved_msg.info;
12286         for (i = 0; i <= result_buffer[0]; i++)
12287           result[i] = result_buffer[i];
12288         plci_b_write_pos = plci->li_plci_b_write_pos;
12289         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12290         if (plci_b == NULL)
12291           break;
12292         li_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12293         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12294         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12295         plci->li_plci_b_write_pos = plci_b_write_pos;
12296       }
12297       else
12298       {
12299         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12300         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12301         {
12302           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12303             UnMapId (Id), (char   *)(FILE_), __LINE__));
12304           Info = _WRONG_MESSAGE_FORMAT;
12305           break;
12306         }
12307         Info = li_check_main_plci (Id, plci);
12308         result_buffer[0] = 7;
12309         result_buffer[3] = 4;
12310         WRITE_WORD (&result_buffer[4], Info);
12311         result_buffer[6] = 0;
12312         if (Info != GOOD)
12313           break;
12314         result = plci->saved_msg.info;
12315         for (i = 0; i <= result_buffer[0]; i++)
12316           result[i] = result_buffer[i];
12317         plci_b_write_pos = plci->li_plci_b_write_pos;
12318         participant_parms_pos = 0;
12319         result_pos = 7;
12320         while (participant_parms_pos < li_req_parms[0].length)
12321         {
12322           result[result_pos] = 6;
12323           result_pos += 7;
12324           WRITE_DWORD (&result[result_pos - 6], 0);
12325           WRITE_WORD (&result[result_pos - 2], GOOD);
12326           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12327             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12328           {
12329             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12330               UnMapId (Id), (char   *)(FILE_), __LINE__));
12331             WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12332             break;
12333           }
12334           if (api_parse (&li_participant_struct[0].info[1],
12335             li_participant_struct[0].length, "d", li_participant_parms))
12336           {
12337             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12338               UnMapId (Id), (char   *)(FILE_), __LINE__));
12339             WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12340             break;
12341           }
12342           plci_b_id = READ_DWORD (li_participant_parms[0].info) & 0xffff;
12343           WRITE_DWORD (&result[result_pos - 6], plci_b_id);
12344           if (sizeof(result) - result_pos < 7)
12345           {
12346             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12347               UnMapId (Id), (char   *)(FILE_), __LINE__));
12348             WRITE_WORD (&result[result_pos - 2], _WRONG_STATE);
12349             break;
12350           }
12351           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12352           if (plci_b != NULL)
12353           {
12354             li2_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12355             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12356             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12357           }
12358           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12359             (&li_req_parms[0].info[1]));
12360         }
12361         result[0] = (byte)(result_pos - 1);
12362         result[3] = (byte)(result_pos - 4);
12363         result[6] = (byte)(result_pos - 7);
12364         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12365         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12366          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12367         {
12368           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12369           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12370         }
12371         else
12372           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12373         plci->li_plci_b_write_pos = plci_b_write_pos;
12374       }
12375       mixer_calculate_coefs (a);
12376       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12377       mixer_notify_update (plci, TRUE);
12378       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12379         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12380       plci->command = 0;
12381       plci->li_cmd = READ_WORD (li_parms[0].info);
12382       start_internal_command (Id, plci, mixer_command);
12383       return (FALSE);
12384
12385     case LI_REQ_SILENT_UPDATE:
12386       if (!plci || !plci->State
12387        || !plci->NL.Id || plci->nl_remove_id
12388        || (plci->li_bchannel_id == 0)
12389        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12390       {
12391         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12392           UnMapId (Id), (char   *)(FILE_), __LINE__));
12393         return (FALSE);
12394       }
12395       plci_b_write_pos = plci->li_plci_b_write_pos;
12396       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12397         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12398       {
12399         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12400           UnMapId (Id), (char   *)(FILE_), __LINE__));
12401         return (FALSE);
12402       }
12403       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12404       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12405        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12406       {
12407         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12408         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12409       }
12410       else
12411         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12412       plci->li_plci_b_write_pos = plci_b_write_pos;
12413       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12414       plci->command = 0;
12415       plci->li_cmd = READ_WORD (li_parms[0].info);
12416       start_internal_command (Id, plci, mixer_command);
12417       return (FALSE);
12418
12419     default:
12420       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12421         UnMapId (Id), (char   *)(FILE_), __LINE__, READ_WORD (li_parms[0].info)));
12422       Info = _FACILITY_NOT_SUPPORTED;
12423     }
12424   }
12425   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12426     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12427   return (FALSE);
12428 }
12429
12430
12431 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12432 {
12433   dword d;
12434   DIVA_CAPI_ADAPTER   *a;
12435     byte result[12];
12436
12437   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12438     UnMapId (Id), (char   *)(FILE_), __LINE__));
12439
12440   a = plci->adapter;
12441   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12442   {
12443     do
12444     {
12445       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12446       if (!(d & LI_PLCI_B_SKIP_FLAG))
12447       {
12448         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12449         {
12450           if (d & LI_PLCI_B_DISC_FLAG)
12451           {
12452             result[0] = 5;
12453             WRITE_WORD (&result[1], LI_IND_DISCONNECT);
12454             result[3] = 2;
12455             WRITE_WORD (&result[4], _LI_USER_INITIATED);
12456           }
12457           else
12458           {
12459             result[0] = 7;
12460             WRITE_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12461             result[3] = 4;
12462             WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12463           }
12464         }
12465         else
12466         {
12467           if (d & LI_PLCI_B_DISC_FLAG)
12468           {
12469             result[0] = 9;
12470             WRITE_WORD (&result[1], LI_IND_DISCONNECT);
12471             result[3] = 6;
12472             WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12473             WRITE_WORD (&result[8], _LI_USER_INITIATED);
12474           }
12475           else
12476           {
12477             result[0] = 7;
12478             WRITE_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12479             result[3] = 4;
12480             WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12481           }
12482         }
12483         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12484           "ws", SELECTOR_LINE_INTERCONNECT, result);
12485       }
12486       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12487         0 : plci->li_plci_b_read_pos + 1;
12488     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12489   }
12490 }
12491
12492
12493 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12494 {
12495   word i, j, ch;
12496   struct xconnect_transfer_address_s s,   *p;
12497   DIVA_CAPI_ADAPTER   *a;
12498
12499   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12500     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12501
12502   a = plci->adapter;
12503   i = 1;
12504   for (i = 1; i < length; i += 16)
12505   {
12506     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12507     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12508     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12509     ch = msg[i+12] | (msg[i+13] << 8);
12510     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12511     if (!a->li_pri && (plci->li_bchannel_id == 2))
12512       j = 1 - j;
12513     j += a->li_base;
12514     if (ch & XCONNECT_CHANNEL_PORT_PC)
12515       p = &(li_config_table[j].send_pc);
12516     else
12517       p = &(li_config_table[j].send_b);
12518     p->card_address.low = s.card_address.low;
12519     p->card_address.high = s.card_address.high;
12520     p->offset = s.offset;
12521     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12522   }
12523   if (plci->internal_command_queue[0]
12524    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12525     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12526     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12527   {
12528     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12529     if (!plci->internal_command)
12530       next_internal_command (Id, plci);
12531   }
12532   mixer_notify_update (plci, TRUE);
12533 }
12534
12535
12536 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12537 {
12538
12539   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12540     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12541
12542 }
12543
12544
12545 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12546 {
12547   word plci_b_write_pos;
12548
12549   plci_b_write_pos = plci->li_plci_b_write_pos;
12550   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12551     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12552   {
12553     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12554       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12555       (char   *)(FILE_), __LINE__));
12556     return (FALSE);
12557   }
12558   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12559   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12560   plci->li_plci_b_write_pos = plci_b_write_pos;
12561   return (TRUE);
12562 }
12563
12564
12565 static void mixer_remove (PLCI   *plci)
12566 {
12567   DIVA_CAPI_ADAPTER   *a;
12568   PLCI   *notify_plci;
12569   dword plci_b_id;
12570   word i, j;
12571
12572   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12573     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12574     (char   *)(FILE_), __LINE__));
12575
12576   a = plci->adapter;
12577   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12578   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12579   {
12580     if ((plci->li_bchannel_id != 0)
12581      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12582     {
12583       i = a->li_base + (plci->li_bchannel_id - 1);
12584       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12585       {
12586         for (j = 0; j < li_total_channels; j++)
12587         {
12588           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12589            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12590           {
12591             notify_plci = li_config_table[j].plci;
12592             if ((notify_plci != NULL)
12593              && (notify_plci != plci)
12594              && (notify_plci->appl != NULL)
12595              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12596              && (notify_plci->State)
12597              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12598             {
12599               mixer_notify_source_removed (notify_plci, plci_b_id);
12600             }
12601           }
12602         }
12603         mixer_clear_config (plci);
12604         mixer_calculate_coefs (a);
12605         mixer_notify_update (plci, TRUE);
12606       }
12607       li_config_table[i].plci = NULL;
12608       plci->li_bchannel_id = 0;
12609     }
12610   }
12611 }
12612
12613
12614 /*------------------------------------------------------------------*/
12615 /* Echo canceller facilities                                        */
12616 /*------------------------------------------------------------------*/
12617
12618
12619 static void ec_write_parameters (PLCI   *plci)
12620 {
12621   word w;
12622     byte parameter_buffer[6];
12623
12624   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12625     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12626     (char   *)(FILE_), __LINE__));
12627
12628   parameter_buffer[0] = 5;
12629   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12630   WRITE_WORD (&parameter_buffer[2], plci->ec_idi_options);
12631   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12632   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12633   WRITE_WORD (&parameter_buffer[4], w);
12634   add_p (plci, FTY, parameter_buffer);
12635   sig_req (plci, TEL_CTRL, 0);
12636   send_req (plci);
12637 }
12638
12639
12640 static void ec_clear_config (PLCI   *plci)
12641 {
12642
12643   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12644     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12645     (char   *)(FILE_), __LINE__));
12646
12647   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12648     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12649   plci->ec_tail_length = 0;
12650 }
12651
12652
12653 static void ec_prepare_switch (dword Id, PLCI   *plci)
12654 {
12655
12656   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12657     UnMapId (Id), (char   *)(FILE_), __LINE__));
12658
12659 }
12660
12661
12662 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12663 {
12664
12665   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12666     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12667
12668   return (GOOD);
12669 }
12670
12671
12672 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12673 {
12674   word Info;
12675
12676   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12677     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12678
12679   Info = GOOD;
12680   if (plci->B1_facilities & B1_FACILITY_EC)
12681   {
12682     switch (plci->adjust_b_state)
12683     {
12684     case ADJUST_B_RESTORE_EC_1:
12685       plci->internal_command = plci->adjust_b_command;
12686       if (plci->sig_req)
12687       {
12688         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12689         break;
12690       }
12691       ec_write_parameters (plci);
12692       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12693       break;
12694     case ADJUST_B_RESTORE_EC_2:
12695       if ((Rc != OK) && (Rc != OK_FC))
12696       {
12697         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12698           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12699         Info = _WRONG_STATE;
12700         break;
12701       }
12702       break;
12703     }
12704   }
12705   return (Info);
12706 }
12707
12708
12709 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12710 {
12711   word internal_command, Info;
12712     byte result[8];
12713
12714   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12715     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12716     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12717
12718   Info = GOOD;
12719   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12720   {
12721     result[0] = 2;
12722     WRITE_WORD (&result[1], EC_SUCCESS);
12723   }
12724   else
12725   {
12726     result[0] = 5;
12727     WRITE_WORD (&result[1], plci->ec_cmd);
12728     result[3] = 2;
12729     WRITE_WORD (&result[4], GOOD);
12730   }
12731   internal_command = plci->internal_command;
12732   plci->internal_command = 0;
12733   switch (plci->ec_cmd)
12734   {
12735   case EC_ENABLE_OPERATION:
12736   case EC_FREEZE_COEFFICIENTS:
12737   case EC_RESUME_COEFFICIENT_UPDATE:
12738   case EC_RESET_COEFFICIENTS:
12739     switch (internal_command)
12740     {
12741     default:
12742       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12743         B1_FACILITY_EC), EC_COMMAND_1);
12744     case EC_COMMAND_1:
12745       if (adjust_b_process (Id, plci, Rc) != GOOD)
12746       {
12747         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12748           UnMapId (Id), (char   *)(FILE_), __LINE__));
12749         Info = _FACILITY_NOT_SUPPORTED;
12750         break;
12751       }
12752       if (plci->internal_command)
12753         return;
12754     case EC_COMMAND_2:
12755       if (plci->sig_req)
12756       {
12757         plci->internal_command = EC_COMMAND_2;
12758         return;
12759       }
12760       plci->internal_command = EC_COMMAND_3;
12761       ec_write_parameters (plci);
12762       return;
12763     case EC_COMMAND_3:
12764       if ((Rc != OK) && (Rc != OK_FC))
12765       {
12766         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12767           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12768         Info = _FACILITY_NOT_SUPPORTED;
12769         break;
12770       }
12771       break;
12772     }
12773     break;
12774
12775   case EC_DISABLE_OPERATION:
12776     switch (internal_command)
12777     {
12778     default:
12779     case EC_COMMAND_1:
12780       if (plci->B1_facilities & B1_FACILITY_EC)
12781       {
12782         if (plci->sig_req)
12783         {
12784           plci->internal_command = EC_COMMAND_1;
12785           return;
12786         }
12787         plci->internal_command = EC_COMMAND_2;
12788         ec_write_parameters (plci);
12789         return;
12790       }
12791       Rc = OK;
12792     case EC_COMMAND_2:
12793       if ((Rc != OK) && (Rc != OK_FC))
12794       {
12795         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12796           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12797         Info = _FACILITY_NOT_SUPPORTED;
12798         break;
12799       }
12800       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12801         ~B1_FACILITY_EC), EC_COMMAND_3);
12802     case EC_COMMAND_3:
12803       if (adjust_b_process (Id, plci, Rc) != GOOD)
12804       {
12805         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12806           UnMapId (Id), (char   *)(FILE_), __LINE__));
12807         Info = _FACILITY_NOT_SUPPORTED;
12808         break;
12809       }
12810       if (plci->internal_command)
12811         return;
12812       break;
12813     }
12814     break;
12815   }
12816   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12817     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12818     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12819 }
12820
12821
12822 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12823 {
12824   word Info;
12825   word opt;
12826     API_PARSE ec_parms[3];
12827     byte result[16];
12828
12829   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12830     UnMapId (Id), (char   *)(FILE_), __LINE__));
12831
12832   Info = GOOD;
12833   result[0] = 0;
12834   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12835   {
12836     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12837       UnMapId (Id), (char   *)(FILE_), __LINE__));
12838     Info = _FACILITY_NOT_SUPPORTED;
12839   }
12840   else
12841   {
12842     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12843     {
12844       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12845       {
12846         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12847           UnMapId (Id), (char   *)(FILE_), __LINE__));
12848         Info = _WRONG_MESSAGE_FORMAT;
12849       }
12850       else
12851       {
12852         if (plci == NULL)
12853         {
12854           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12855             UnMapId (Id), (char   *)(FILE_), __LINE__));
12856           Info = _WRONG_IDENTIFIER;
12857         }
12858         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12859         {
12860           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12861             UnMapId (Id), (char   *)(FILE_), __LINE__));
12862           Info = _WRONG_STATE;
12863         }
12864         else
12865         {
12866           plci->command = 0;
12867           plci->ec_cmd = READ_WORD (ec_parms[0].info);
12868           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12869           result[0] = 2;
12870           WRITE_WORD (&result[1], EC_SUCCESS);
12871           if (msg[1].length >= 4)
12872           {
12873             opt = READ_WORD (&ec_parms[0].info[2]);
12874             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12875               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12876             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12877               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12878             if (opt & EC_DETECT_DISABLE_TONE)
12879               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12880             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12881               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12882             if (msg[1].length >= 6)
12883             {
12884               plci->ec_tail_length = READ_WORD (&ec_parms[0].info[4]);
12885             }
12886           }
12887           switch (plci->ec_cmd)
12888           {
12889           case EC_ENABLE_OPERATION:
12890             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12891             start_internal_command (Id, plci, ec_command);
12892             return (FALSE);
12893
12894           case EC_DISABLE_OPERATION:
12895             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12896               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12897               LEC_RESET_COEFFICIENTS;
12898             start_internal_command (Id, plci, ec_command);
12899             return (FALSE);
12900
12901           case EC_FREEZE_COEFFICIENTS:
12902             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12903             start_internal_command (Id, plci, ec_command);
12904             return (FALSE);
12905
12906           case EC_RESUME_COEFFICIENT_UPDATE:
12907             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12908             start_internal_command (Id, plci, ec_command);
12909             return (FALSE);
12910
12911           case EC_RESET_COEFFICIENTS:
12912             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12913             start_internal_command (Id, plci, ec_command);
12914             return (FALSE);
12915
12916           default:
12917             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12918               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12919             WRITE_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12920           }
12921         }
12922       }
12923     }
12924     else
12925     {
12926       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12927       {
12928         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12929           UnMapId (Id), (char   *)(FILE_), __LINE__));
12930         Info = _WRONG_MESSAGE_FORMAT;
12931       }
12932       else
12933       {
12934         if (READ_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12935         {
12936           result[0] = 11;
12937           WRITE_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12938           result[3] = 8;
12939           WRITE_WORD (&result[4], GOOD);
12940           WRITE_WORD (&result[6], 0x0007);
12941           WRITE_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12942           WRITE_WORD (&result[10], 0);
12943         }
12944         else if (plci == NULL)
12945         {
12946           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12947             UnMapId (Id), (char   *)(FILE_), __LINE__));
12948           Info = _WRONG_IDENTIFIER;
12949         }
12950         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12951         {
12952           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12953             UnMapId (Id), (char   *)(FILE_), __LINE__));
12954           Info = _WRONG_STATE;
12955         }
12956         else
12957         {
12958           plci->command = 0;
12959           plci->ec_cmd = READ_WORD (ec_parms[0].info);
12960           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12961           result[0] = 5;
12962           WRITE_WORD (&result[1], plci->ec_cmd);
12963           result[3] = 2;
12964           WRITE_WORD (&result[4], GOOD);
12965           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12966             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12967           plci->ec_tail_length = 0;
12968           if (ec_parms[1].length >= 2)
12969           {
12970             opt = READ_WORD (&ec_parms[1].info[1]);
12971             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12972               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12973             if (opt & EC_DETECT_DISABLE_TONE)
12974               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12975             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12976               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12977             if (ec_parms[1].length >= 4)
12978             {
12979               plci->ec_tail_length = READ_WORD (&ec_parms[1].info[3]);
12980             }
12981           }
12982           switch (plci->ec_cmd)
12983           {
12984           case EC_ENABLE_OPERATION:
12985             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12986             start_internal_command (Id, plci, ec_command);
12987             return (FALSE);
12988
12989           case EC_DISABLE_OPERATION:
12990             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12991               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12992               LEC_RESET_COEFFICIENTS;
12993             start_internal_command (Id, plci, ec_command);
12994             return (FALSE);
12995
12996           default:
12997             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12998               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12999             WRITE_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13000           }
13001         }
13002       }
13003     }
13004   }
13005   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13006     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13007     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13008   return (FALSE);
13009 }
13010
13011
13012 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13013 {
13014     byte result[8];
13015
13016   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13017     UnMapId (Id), (char   *)(FILE_), __LINE__));
13018
13019   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13020   {
13021     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13022     {
13023       result[0] = 2;
13024       WRITE_WORD (&result[1], 0);
13025       switch (msg[1])
13026       {
13027       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13028         WRITE_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13029         break;
13030       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13031         WRITE_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13032         break;
13033       case LEC_DISABLE_RELEASED:
13034         WRITE_WORD (&result[1], EC_BYPASS_RELEASED);
13035         break;
13036       }
13037     }
13038     else
13039     {
13040       result[0] = 5;
13041       WRITE_WORD (&result[1], EC_BYPASS_INDICATION);
13042       result[3] = 2;
13043       WRITE_WORD (&result[4], 0);
13044       switch (msg[1])
13045       {
13046       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13047         WRITE_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13048         break;
13049       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13050         WRITE_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13051         break;
13052       case LEC_DISABLE_RELEASED:
13053         WRITE_WORD (&result[4], EC_BYPASS_RELEASED);
13054         break;
13055       }
13056     }
13057     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13058       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13059   }
13060 }
13061
13062
13063
13064 /*------------------------------------------------------------------*/
13065 /* Advanced voice                                                   */
13066 /*------------------------------------------------------------------*/
13067
13068 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13069 {
13070   DIVA_CAPI_ADAPTER   *a;
13071   word i;
13072   byte *p;
13073
13074   word w, n, j, k;
13075   byte ch_map[MIXER_CHANNELS_BRI];
13076
13077     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13078
13079   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13080     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13081     (char   *)(FILE_), __LINE__, write_command));
13082
13083   a = plci->adapter;
13084   p = coef_buffer + 1;
13085   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13086   i = 0;
13087   while (i + sizeof(word) <= a->adv_voice_coef_length)
13088   {
13089     WRITE_WORD (p, READ_WORD (a->adv_voice_coef_buffer + i));
13090     p += 2;
13091     i += 2;
13092   }
13093   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13094   {
13095     WRITE_WORD (p, 0x8000);
13096     p += 2;
13097     i += 2;
13098   }
13099
13100   if (!a->li_pri && (plci->li_bchannel_id == 0))
13101   {
13102     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13103     {
13104       plci->li_bchannel_id = 1;
13105       li_config_table[a->li_base].plci = plci;
13106       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13107         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13108         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13109     }
13110     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13111     {
13112       plci->li_bchannel_id = 2;
13113       li_config_table[a->li_base + 1].plci = plci;
13114       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13115         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13116         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13117     }
13118   }
13119   if (!a->li_pri && (plci->li_bchannel_id != 0)
13120    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13121   {
13122     i = a->li_base + (plci->li_bchannel_id - 1);
13123     switch (write_command)
13124     {
13125     case ADV_VOICE_WRITE_ACTIVATION:
13126       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13127       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13128       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13129       {
13130         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13131         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13132       }
13133       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13134       {
13135         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13136         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13137         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13138         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13139       }
13140       mixer_calculate_coefs (a);
13141       li_config_table[i].curchnl = li_config_table[i].channel;
13142       li_config_table[j].curchnl = li_config_table[j].channel;
13143       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13144         li_config_table[k].curchnl = li_config_table[k].channel;
13145       break;
13146
13147     case ADV_VOICE_WRITE_DEACTIVATION:
13148       for (j = 0; j < li_total_channels; j++)
13149       {
13150         li_config_table[i].flag_table[j] = 0;
13151         li_config_table[j].flag_table[i] = 0;
13152       }
13153       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13154       for (j = 0; j < li_total_channels; j++)
13155       {
13156         li_config_table[k].flag_table[j] = 0;
13157         li_config_table[j].flag_table[k] = 0;
13158       }
13159       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13160       {
13161         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13162         for (j = 0; j < li_total_channels; j++)
13163         {
13164           li_config_table[k].flag_table[j] = 0;
13165           li_config_table[j].flag_table[k] = 0;
13166         }
13167       }
13168       mixer_calculate_coefs (a);
13169       break;
13170     }
13171     if (plci->B1_facilities & B1_FACILITY_MIXER)
13172     {
13173       w = 0;
13174       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13175         w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13176       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13177         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13178       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13179         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13180       *(p++) = (byte) w;
13181       *(p++) = (byte)(w >> 8);
13182       for (j = 0; j < sizeof(ch_map); j += 2)
13183       {
13184         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13185         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13186       }
13187       for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
13188       {
13189         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13190         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13191         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13192         {
13193           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13194           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13195           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13196         }
13197         else
13198         {
13199           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13200             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13201         }
13202       }
13203     }
13204     else
13205     {
13206       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13207         *(p++) = a->adv_voice_coef_buffer[i];
13208     }
13209   }
13210   else
13211
13212   {
13213     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13214       *(p++) = a->adv_voice_coef_buffer[i];
13215   }
13216   coef_buffer[0] = (p - coef_buffer) - 1;
13217   add_p (plci, FTY, coef_buffer);
13218   sig_req (plci, TEL_CTRL, 0);
13219   send_req (plci);
13220 }
13221
13222
13223 static void adv_voice_clear_config (PLCI   *plci)
13224 {
13225   DIVA_CAPI_ADAPTER   *a;
13226
13227   word i, j;
13228
13229
13230   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13231     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13232     (char   *)(FILE_), __LINE__));
13233
13234   a = plci->adapter;
13235   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13236   {
13237     a->adv_voice_coef_length = 0;
13238
13239     if (!a->li_pri && (plci->li_bchannel_id != 0)
13240      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13241     {
13242       i = a->li_base + (plci->li_bchannel_id - 1);
13243       li_config_table[i].curchnl = 0;
13244       li_config_table[i].channel = 0;
13245       li_config_table[i].chflags = 0;
13246       for (j = 0; j < li_total_channels; j++)
13247       {
13248         li_config_table[i].flag_table[j] = 0;
13249         li_config_table[j].flag_table[i] = 0;
13250         li_config_table[i].coef_table[j] = 0;
13251         li_config_table[j].coef_table[i] = 0;
13252       }
13253       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13254       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13255       li_config_table[i].curchnl = 0;
13256       li_config_table[i].channel = 0;
13257       li_config_table[i].chflags = 0;
13258       for (j = 0; j < li_total_channels; j++)
13259       {
13260         li_config_table[i].flag_table[j] = 0;
13261         li_config_table[j].flag_table[i] = 0;
13262         li_config_table[i].coef_table[j] = 0;
13263         li_config_table[j].coef_table[i] = 0;
13264       }
13265       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13266       {
13267         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13268         li_config_table[i].curchnl = 0;
13269         li_config_table[i].channel = 0;
13270         li_config_table[i].chflags = 0;
13271         for (j = 0; j < li_total_channels; j++)
13272         {
13273           li_config_table[i].flag_table[j] = 0;
13274           li_config_table[j].flag_table[i] = 0;
13275           li_config_table[i].coef_table[j] = 0;
13276           li_config_table[j].coef_table[i] = 0;
13277         }
13278       }
13279     }
13280
13281   }
13282 }
13283
13284
13285 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13286 {
13287
13288   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13289     UnMapId (Id), (char   *)(FILE_), __LINE__));
13290
13291 }
13292
13293
13294 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13295 {
13296
13297   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13298     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13299
13300   return (GOOD);
13301 }
13302
13303
13304 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13305 {
13306   DIVA_CAPI_ADAPTER   *a;
13307   word Info;
13308
13309   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13310     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13311
13312   Info = GOOD;
13313   a = plci->adapter;
13314   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13315    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13316   {
13317     switch (plci->adjust_b_state)
13318     {
13319     case ADJUST_B_RESTORE_VOICE_1:
13320       plci->internal_command = plci->adjust_b_command;
13321       if (plci->sig_req)
13322       {
13323         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13324         break;
13325       }
13326       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13327       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13328       break;
13329     case ADJUST_B_RESTORE_VOICE_2:
13330       if ((Rc != OK) && (Rc != OK_FC))
13331       {
13332         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13333           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13334         Info = _WRONG_STATE;
13335         break;
13336       }
13337       break;
13338     }
13339   }
13340   return (Info);
13341 }
13342
13343
13344
13345
13346 /*------------------------------------------------------------------*/
13347 /* B1 resource switching                                            */
13348 /*------------------------------------------------------------------*/
13349
13350 static byte b1_facilities_table[] =
13351 {
13352   0x00,  /* 0  No bchannel resources      */
13353   0x00,  /* 1  Codec (automatic law)      */
13354   0x00,  /* 2  Codec (A-law)              */
13355   0x00,  /* 3  Codec (y-law)              */
13356   0x00,  /* 4  HDLC for X.21              */
13357   0x00,  /* 5  HDLC                       */
13358   0x00,  /* 6  External Device 0          */
13359   0x00,  /* 7  External Device 1          */
13360   0x00,  /* 8  HDLC 56k                   */
13361   0x00,  /* 9  Transparent                */
13362   0x00,  /* 10 Loopback to network        */
13363   0x00,  /* 11 Test pattern to net        */
13364   0x00,  /* 12 Rate adaptation sync       */
13365   0x00,  /* 13 Rate adaptation async      */
13366   0x00,  /* 14 R-Interface                */
13367   0x00,  /* 15 HDLC 128k leased line      */
13368   0x00,  /* 16 FAX                        */
13369   0x00,  /* 17 Modem async                */
13370   0x00,  /* 18 Modem sync HDLC            */
13371   0x00,  /* 19 V.110 async HDLC           */
13372   0x12,  /* 20 Adv voice (Trans,mixer)    */
13373   0x00,  /* 21 Codec connected to IC      */
13374   0x0c,  /* 22 Trans,DTMF                 */
13375   0x1e,  /* 23 Trans,DTMF+mixer           */
13376   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13377   0x13,  /* 25 Trans,mixer+local          */
13378   0x12,  /* 26 HDLC,mixer                 */
13379   0x12,  /* 27 HDLC 56k,mixer             */
13380   0x2c,  /* 28 Trans,LEC+DTMF             */
13381   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13382   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13383   0x2c,  /* 31 RTP,LEC+DTMF               */
13384   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13385   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13386   0x00,  /* 34 Signaling task             */
13387   0x00,  /* 35 PIAFS                      */
13388   0x0c,  /* 36 Trans,DTMF+TONE            */
13389   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13390   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13391 };
13392
13393
13394 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13395 {
13396   word b1_facilities;
13397
13398   b1_facilities = b1_facilities_table[b1_resource];
13399   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13400   {
13401
13402     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13403        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13404
13405     {
13406       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13407         b1_facilities |= B1_FACILITY_DTMFX;
13408       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13409         b1_facilities |= B1_FACILITY_DTMFR;
13410     }
13411   }
13412   if ((b1_resource == 17) || (b1_resource == 18))
13413   {
13414     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13415       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13416   }
13417 /*
13418   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13419     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13420     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13421 */
13422   return (b1_facilities);
13423 }
13424
13425
13426 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13427 {
13428   byte b;
13429
13430   switch (b1_resource)
13431   {
13432   case 5:
13433   case 26:
13434     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13435       b = 26;
13436     else
13437       b = 5;
13438     break;
13439
13440   case 8:
13441   case 27:
13442     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13443       b = 27;
13444     else
13445       b = 8;
13446     break;
13447
13448   case 9:
13449   case 20:
13450   case 22:
13451   case 23:
13452   case 24:
13453   case 25:
13454   case 28:
13455   case 29:
13456   case 30:
13457   case 36:
13458   case 37:
13459   case 38:
13460     if (b1_facilities & B1_FACILITY_EC)
13461     {
13462       if (b1_facilities & B1_FACILITY_LOCAL)
13463         b = 30;
13464       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13465         b = 29;
13466       else
13467         b = 28;
13468     }
13469
13470     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13471       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13472        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13473     {
13474       if (b1_facilities & B1_FACILITY_LOCAL)
13475         b = 38;
13476       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13477         b = 37;
13478       else
13479         b = 36;
13480     }
13481
13482     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13483       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13484      || ((b1_facilities & B1_FACILITY_DTMFR)
13485       && ((b1_facilities & B1_FACILITY_MIXER)
13486        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13487      || ((b1_facilities & B1_FACILITY_DTMFX)
13488       && ((b1_facilities & B1_FACILITY_MIXER)
13489        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13490     {
13491       if (b1_facilities & B1_FACILITY_LOCAL)
13492         b = 24;
13493       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13494         b = 23;
13495       else
13496         b = 22;
13497     }
13498     else
13499     {
13500       if (b1_facilities & B1_FACILITY_LOCAL)
13501         b = 25;
13502       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13503         b = 20;
13504       else
13505         b = 9;
13506     }
13507     break;
13508
13509   case 31:
13510   case 32:
13511   case 33:
13512     if (b1_facilities & B1_FACILITY_LOCAL)
13513       b = 33;
13514     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13515       b = 32;
13516     else
13517       b = 31;
13518     break;
13519
13520   default:
13521     b = b1_resource;
13522   }
13523   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13524     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13525     (char   *)(FILE_), __LINE__,
13526     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13527   return (b);
13528 }
13529
13530
13531 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13532 {
13533   word removed_facilities;
13534
13535   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13536     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13537     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13538     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13539
13540   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13541   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13542
13543   if (removed_facilities & B1_FACILITY_EC)
13544     ec_clear_config (plci);
13545
13546
13547   if (removed_facilities & B1_FACILITY_DTMFR)
13548   {
13549     dtmf_rec_clear_config (plci);
13550     dtmf_parameter_clear_config (plci);
13551   }
13552   if (removed_facilities & B1_FACILITY_DTMFX)
13553     dtmf_send_clear_config (plci);
13554
13555
13556   if (removed_facilities & B1_FACILITY_MIXER)
13557     mixer_clear_config (plci);
13558
13559   if (removed_facilities & B1_FACILITY_VOICE)
13560     adv_voice_clear_config (plci);
13561   plci->B1_facilities = new_b1_facilities;
13562 }
13563
13564
13565 static void adjust_b_clear (PLCI   *plci)
13566 {
13567
13568   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13569     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13570     (char   *)(FILE_), __LINE__));
13571
13572   plci->adjust_b_restore = FALSE;
13573 }
13574
13575
13576 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13577 {
13578   word Info;
13579   byte b1_resource;
13580   NCCI   * ncci_ptr;
13581     API_PARSE bp[2];
13582
13583   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13584     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13585
13586   Info = GOOD;
13587   switch (plci->adjust_b_state)
13588   {
13589   case ADJUST_B_START:
13590     if ((plci->adjust_b_parms_msg == NULL)
13591      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13592      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13593       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13594     {
13595       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13596         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13597       if (b1_resource == plci->B1_resource)
13598       {
13599         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13600         break;
13601       }
13602       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13603       {
13604         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13605           UnMapId (Id), (char   *)(FILE_), __LINE__,
13606           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13607         Info = _WRONG_STATE;
13608         break;
13609       }
13610     }
13611     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13612     {
13613
13614       mixer_prepare_switch (Id, plci);
13615
13616
13617       dtmf_prepare_switch (Id, plci);
13618       dtmf_parameter_prepare_switch (Id, plci);
13619
13620
13621       ec_prepare_switch (Id, plci);
13622
13623       adv_voice_prepare_switch (Id, plci);
13624     }
13625     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13626     Rc = OK;
13627   case ADJUST_B_SAVE_MIXER_1:
13628     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13629     {
13630
13631       Info = mixer_save_config (Id, plci, Rc);
13632       if ((Info != GOOD) || plci->internal_command)
13633         break;
13634
13635     }
13636     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13637     Rc = OK;
13638   case ADJUST_B_SAVE_DTMF_1:
13639     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13640     {
13641
13642       Info = dtmf_save_config (Id, plci, Rc);
13643       if ((Info != GOOD) || plci->internal_command)
13644         break;
13645
13646     }
13647     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13648   case ADJUST_B_REMOVE_L23_1:
13649     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13650      && plci->NL.Id && !plci->nl_remove_id)
13651     {
13652       plci->internal_command = plci->adjust_b_command;
13653       if (plci->adjust_b_ncci != 0)
13654       {
13655         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13656         while (ncci_ptr->data_pending)
13657         {
13658           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13659           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13660         }
13661         while (ncci_ptr->data_ack_pending)
13662           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13663       }
13664       nl_req_ncci (plci, REMOVE,
13665         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13666       send_req (plci);
13667       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13668       break;
13669     }
13670     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13671     Rc = OK;
13672   case ADJUST_B_REMOVE_L23_2:
13673     if ((Rc != OK) && (Rc != OK_FC))
13674     {
13675       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13676         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13677       Info = _WRONG_STATE;
13678       break;
13679     }
13680     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13681     {
13682       if (plci_nl_busy (plci))
13683       {
13684         plci->internal_command = plci->adjust_b_command;
13685         break;
13686       }
13687     }
13688     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13689     Rc = OK;
13690   case ADJUST_B_SAVE_EC_1:
13691     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13692     {
13693
13694       Info = ec_save_config (Id, plci, Rc);
13695       if ((Info != GOOD) || plci->internal_command)
13696         break;
13697
13698     }
13699     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13700     Rc = OK;
13701   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13702     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13703     {
13704
13705       Info = dtmf_parameter_save_config (Id, plci, Rc);
13706       if ((Info != GOOD) || plci->internal_command)
13707         break;
13708
13709     }
13710     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13711     Rc = OK;
13712   case ADJUST_B_SAVE_VOICE_1:
13713     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13714     {
13715       Info = adv_voice_save_config (Id, plci, Rc);
13716       if ((Info != GOOD) || plci->internal_command)
13717         break;
13718     }
13719     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13720   case ADJUST_B_SWITCH_L1_1:
13721     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13722     {
13723       if (plci->sig_req)
13724       {
13725         plci->internal_command = plci->adjust_b_command;
13726         break;
13727       }
13728       if (plci->adjust_b_parms_msg != NULL)
13729         api_load_msg (plci->adjust_b_parms_msg, bp);
13730       else
13731         api_load_msg (&plci->B_protocol, bp);
13732       Info = add_b1 (plci, bp,
13733         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13734         plci->adjust_b_facilities);
13735       if (Info != GOOD)
13736       {
13737         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13738           UnMapId (Id), (char   *)(FILE_), __LINE__,
13739           plci->B1_resource, plci->adjust_b_facilities));
13740         break;
13741       }
13742       plci->internal_command = plci->adjust_b_command;
13743       sig_req (plci, RESOURCES, 0);
13744       send_req (plci);
13745       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13746       break;
13747     }
13748     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13749     Rc = OK;
13750   case ADJUST_B_SWITCH_L1_2:
13751     if ((Rc != OK) && (Rc != OK_FC))
13752     {
13753       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13754         UnMapId (Id), (char   *)(FILE_), __LINE__,
13755         Rc, plci->B1_resource, plci->adjust_b_facilities));
13756       Info = _WRONG_STATE;
13757       break;
13758     }
13759     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13760     Rc = OK;
13761   case ADJUST_B_RESTORE_VOICE_1:
13762   case ADJUST_B_RESTORE_VOICE_2:
13763     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13764     {
13765       Info = adv_voice_restore_config (Id, plci, Rc);
13766       if ((Info != GOOD) || plci->internal_command)
13767         break;
13768     }
13769     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13770     Rc = OK;
13771   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13772   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13773     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13774     {
13775
13776       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13777       if ((Info != GOOD) || plci->internal_command)
13778         break;
13779
13780     }
13781     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13782     Rc = OK;
13783   case ADJUST_B_RESTORE_EC_1:
13784   case ADJUST_B_RESTORE_EC_2:
13785     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13786     {
13787
13788       Info = ec_restore_config (Id, plci, Rc);
13789       if ((Info != GOOD) || plci->internal_command)
13790         break;
13791
13792     }
13793     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13794   case ADJUST_B_ASSIGN_L23_1:
13795     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13796     {
13797       if (plci_nl_busy (plci))
13798       {
13799         plci->internal_command = plci->adjust_b_command;
13800         break;
13801       }
13802       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13803         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13804       if (plci->adjust_b_parms_msg != NULL)
13805         api_load_msg (plci->adjust_b_parms_msg, bp);
13806       else
13807         api_load_msg (&plci->B_protocol, bp);
13808       Info = add_b23 (plci, bp);
13809       if (Info != GOOD)
13810       {
13811         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13812           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13813         break;
13814       }
13815       plci->internal_command = plci->adjust_b_command;
13816       nl_req_ncci (plci, ASSIGN, 0);
13817       send_req (plci);
13818       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13819       break;
13820     }
13821     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13822     Rc = ASSIGN_OK;
13823   case ADJUST_B_ASSIGN_L23_2:
13824     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13825     {
13826       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13827         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13828       Info = _WRONG_STATE;
13829       break;
13830     }
13831     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13832     {
13833       if (Rc != ASSIGN_OK)
13834       {
13835         plci->internal_command = plci->adjust_b_command;
13836         break;
13837       }
13838     }
13839     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13840     {
13841       plci->adjust_b_restore = TRUE;
13842       break;
13843     }
13844     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13845   case ADJUST_B_CONNECT_1:
13846     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13847     {
13848       plci->internal_command = plci->adjust_b_command;
13849       if (plci_nl_busy (plci))
13850         break;
13851       nl_req_ncci (plci, N_CONNECT, 0);
13852       send_req (plci);
13853       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13854       break;
13855     }
13856     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13857     Rc = OK;
13858   case ADJUST_B_CONNECT_2:
13859   case ADJUST_B_CONNECT_3:
13860   case ADJUST_B_CONNECT_4:
13861     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13862     {
13863       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13864         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13865       Info = _WRONG_STATE;
13866       break;
13867     }
13868     if (Rc == OK)
13869     {
13870       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13871       {
13872         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13873         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13874       }
13875       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13876         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13877       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13878         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13879     }
13880     else if (Rc == 0)
13881     {
13882       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13883         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13884       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13885         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13886     }
13887     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13888     {
13889       plci->internal_command = plci->adjust_b_command;
13890       break;
13891     }
13892     Rc = OK;
13893   case ADJUST_B_RESTORE_DTMF_1:
13894   case ADJUST_B_RESTORE_DTMF_2:
13895     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13896     {
13897
13898       Info = dtmf_restore_config (Id, plci, Rc);
13899       if ((Info != GOOD) || plci->internal_command)
13900         break;
13901
13902     }
13903     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13904     Rc = OK;
13905   case ADJUST_B_RESTORE_MIXER_1:
13906   case ADJUST_B_RESTORE_MIXER_2:
13907   case ADJUST_B_RESTORE_MIXER_3:
13908   case ADJUST_B_RESTORE_MIXER_4:
13909   case ADJUST_B_RESTORE_MIXER_5:
13910   case ADJUST_B_RESTORE_MIXER_6:
13911   case ADJUST_B_RESTORE_MIXER_7:
13912     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13913     {
13914
13915       Info = mixer_restore_config (Id, plci, Rc);
13916       if ((Info != GOOD) || plci->internal_command)
13917         break;
13918
13919     }
13920     plci->adjust_b_state = ADJUST_B_END;
13921   case ADJUST_B_END:
13922     break;
13923   }
13924   return (Info);
13925 }
13926
13927
13928 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13929 {
13930
13931   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13932     UnMapId (Id), (char   *)(FILE_), __LINE__,
13933     plci->B1_resource, b1_facilities));
13934
13935   plci->adjust_b_parms_msg = bp_msg;
13936   plci->adjust_b_facilities = b1_facilities;
13937   plci->adjust_b_command = internal_command;
13938   plci->adjust_b_ncci = (word)(Id >> 16);
13939   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13940     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13941   else
13942     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13943   plci->adjust_b_state = ADJUST_B_START;
13944   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13945     UnMapId (Id), (char   *)(FILE_), __LINE__,
13946     plci->B1_resource, b1_facilities));
13947 }
13948
13949
13950 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13951 {
13952   word internal_command;
13953
13954   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13955     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13956
13957   internal_command = plci->internal_command;
13958   plci->internal_command = 0;
13959   switch (internal_command)
13960   {
13961   default:
13962     plci->command = 0;
13963     if (plci->req_in != 0)
13964     {
13965       plci->internal_command = ADJUST_B_RESTORE_1;
13966       break;
13967     }
13968     Rc = OK;
13969   case ADJUST_B_RESTORE_1:
13970     if ((Rc != OK) && (Rc != OK_FC))
13971     {
13972       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13973         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13974     }
13975     plci->adjust_b_parms_msg = NULL;
13976     plci->adjust_b_facilities = plci->B1_facilities;
13977     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13978     plci->adjust_b_ncci = (word)(Id >> 16);
13979     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13980     plci->adjust_b_state = ADJUST_B_START;
13981     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13982       UnMapId (Id), (char   *)(FILE_), __LINE__));
13983   case ADJUST_B_RESTORE_2:
13984     if (adjust_b_process (Id, plci, Rc) != GOOD)
13985     {
13986       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13987         UnMapId (Id), (char   *)(FILE_), __LINE__));
13988     }
13989     if (plci->internal_command)
13990       break;
13991     break;
13992   }
13993 }
13994
13995
13996 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
13997 {
13998   word Info;
13999   word internal_command;
14000
14001   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14002     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14003
14004   Info = GOOD;
14005   internal_command = plci->internal_command;
14006   plci->internal_command = 0;
14007   switch (internal_command)
14008   {
14009   default:
14010     plci->command = 0;
14011     plci->adjust_b_parms_msg = NULL;
14012     plci->adjust_b_facilities = plci->B1_facilities;
14013     plci->adjust_b_command = RESET_B3_COMMAND_1;
14014     plci->adjust_b_ncci = (word)(Id >> 16);
14015     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14016     plci->adjust_b_state = ADJUST_B_START;
14017     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14018       UnMapId (Id), (char   *)(FILE_), __LINE__));
14019   case RESET_B3_COMMAND_1:
14020     Info = adjust_b_process (Id, plci, Rc);
14021     if (Info != GOOD)
14022     {
14023       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14024         UnMapId (Id), (char   *)(FILE_), __LINE__));
14025       break;
14026     }
14027     if (plci->internal_command)
14028       return;
14029     break;
14030   }
14031 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14032   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14033 }
14034
14035
14036 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14037 {
14038   word Info;
14039   word internal_command;
14040   byte esc_chi[3];
14041
14042   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14043     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14044
14045   Info = GOOD;
14046   internal_command = plci->internal_command;
14047   plci->internal_command = 0;
14048   switch (internal_command)
14049   {
14050   default:
14051     plci->command = 0;
14052     plci->adjust_b_parms_msg = &plci->saved_msg;
14053     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14054       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14055     else
14056       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14057     plci->adjust_b_command = SELECT_B_COMMAND_1;
14058     plci->adjust_b_ncci = (word)(Id >> 16);
14059     if (plci->saved_msg.parms[0].length == 0)
14060     {
14061       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14062         ADJUST_B_MODE_NO_RESOURCE;
14063     }
14064     else
14065     {
14066       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14067         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14068     }
14069     plci->adjust_b_state = ADJUST_B_START;
14070     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14071       UnMapId (Id), (char   *)(FILE_), __LINE__));
14072   case SELECT_B_COMMAND_1:
14073     Info = adjust_b_process (Id, plci, Rc);
14074     if (Info != GOOD)
14075     {
14076       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14077         UnMapId (Id), (char   *)(FILE_), __LINE__));
14078       break;
14079     }
14080     if (plci->internal_command)
14081       return;
14082     if (plci->tel == ADV_VOICE)
14083     {
14084       esc_chi[0] = 0x02;
14085       esc_chi[1] = 0x18;
14086       esc_chi[2] = plci->b_channel;
14087       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14088     }
14089     break;
14090   }
14091   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14092 }
14093
14094
14095 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14096 {
14097   word Info;
14098   word internal_command;
14099
14100   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14101     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14102
14103   Info = GOOD;
14104   internal_command = plci->internal_command;
14105   plci->internal_command = 0;
14106   switch (internal_command)
14107   {
14108   default:
14109     plci->command = 0;
14110   case FAX_CONNECT_ACK_COMMAND_1:
14111     if (plci_nl_busy (plci))
14112     {
14113       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14114       return;
14115     }
14116     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14117     plci->NData[0].P = plci->fax_connect_info_buffer;
14118     plci->NData[0].PLength = plci->fax_connect_info_length;
14119     plci->NL.X = plci->NData;
14120     plci->NL.ReqCh = 0;
14121     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14122     plci->adapter->request (&plci->NL);
14123     return;
14124   case FAX_CONNECT_ACK_COMMAND_2:
14125     if ((Rc != OK) && (Rc != OK_FC))
14126     {
14127       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14128         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14129       break;
14130     }
14131   }
14132   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14133    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14134   {
14135     if (plci->B3_prot == 4)
14136       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14137     else
14138       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14139     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14140   }
14141 }
14142
14143
14144 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14145 {
14146   word Info;
14147   word internal_command;
14148
14149   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14150     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14151
14152   Info = GOOD;
14153   internal_command = plci->internal_command;
14154   plci->internal_command = 0;
14155   switch (internal_command)
14156   {
14157   default:
14158     plci->command = 0;
14159   case FAX_EDATA_ACK_COMMAND_1:
14160     if (plci_nl_busy (plci))
14161     {
14162       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14163       return;
14164     }
14165     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14166     plci->NData[0].P = plci->fax_connect_info_buffer;
14167     plci->NData[0].PLength = plci->fax_edata_ack_length;
14168     plci->NL.X = plci->NData;
14169     plci->NL.ReqCh = 0;
14170     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14171     plci->adapter->request (&plci->NL);
14172     return;
14173   case FAX_EDATA_ACK_COMMAND_2:
14174     if ((Rc != OK) && (Rc != OK_FC))
14175     {
14176       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14177         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14178       break;
14179     }
14180   }
14181 }
14182
14183
14184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14185 {
14186   word Info;
14187   word internal_command;
14188
14189   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14190     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14191
14192   Info = GOOD;
14193   internal_command = plci->internal_command;
14194   plci->internal_command = 0;
14195   switch (internal_command)
14196   {
14197   default:
14198     plci->command = 0;
14199   case FAX_CONNECT_INFO_COMMAND_1:
14200     if (plci_nl_busy (plci))
14201     {
14202       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14203       return;
14204     }
14205     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14206     plci->NData[0].P = plci->fax_connect_info_buffer;
14207     plci->NData[0].PLength = plci->fax_connect_info_length;
14208     plci->NL.X = plci->NData;
14209     plci->NL.ReqCh = 0;
14210     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14211     plci->adapter->request (&plci->NL);
14212     return;
14213   case FAX_CONNECT_INFO_COMMAND_2:
14214     if ((Rc != OK) && (Rc != OK_FC))
14215     {
14216       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14217         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14218       Info = _WRONG_STATE;
14219       break;
14220     }
14221     if (plci_nl_busy (plci))
14222     {
14223       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14224       return;
14225     }
14226     plci->command = _CONNECT_B3_R;
14227     nl_req_ncci (plci, N_CONNECT, 0);
14228     send_req (plci);
14229     return;
14230   }
14231   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14232 }
14233
14234
14235 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14236 {
14237   word Info;
14238   word internal_command;
14239
14240   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14241     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14242
14243   Info = GOOD;
14244   internal_command = plci->internal_command;
14245   plci->internal_command = 0;
14246   switch (internal_command)
14247   {
14248   default:
14249     plci->command = 0;
14250     plci->adjust_b_parms_msg = NULL;
14251     plci->adjust_b_facilities = plci->B1_facilities;
14252     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14253     plci->adjust_b_ncci = (word)(Id >> 16);
14254     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14255     plci->adjust_b_state = ADJUST_B_START;
14256     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14257       UnMapId (Id), (char   *)(FILE_), __LINE__));
14258   case FAX_ADJUST_B23_COMMAND_1:
14259     Info = adjust_b_process (Id, plci, Rc);
14260     if (Info != GOOD)
14261     {
14262       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14263         UnMapId (Id), (char   *)(FILE_), __LINE__));
14264       break;
14265     }
14266     if (plci->internal_command)
14267       return;
14268   case FAX_ADJUST_B23_COMMAND_2:
14269     if (plci_nl_busy (plci))
14270     {
14271       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14272       return;
14273     }
14274     plci->command = _CONNECT_B3_R;
14275     nl_req_ncci (plci, N_CONNECT, 0);
14276     send_req (plci);
14277     return;
14278   }
14279   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14280 }
14281
14282
14283 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14284 {
14285   word internal_command;
14286
14287   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14288     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14289
14290   internal_command = plci->internal_command;
14291   plci->internal_command = 0;
14292   switch (internal_command)
14293   {
14294   default:
14295     plci->command = 0;
14296     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14297     return;
14298   case FAX_DISCONNECT_COMMAND_1:
14299   case FAX_DISCONNECT_COMMAND_2:
14300   case FAX_DISCONNECT_COMMAND_3:
14301     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14302     {
14303       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14304         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14305       break;
14306     }
14307     if (Rc == OK)
14308     {
14309       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14310        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14311       {
14312         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14313       }
14314     }
14315     else if (Rc == 0)
14316     {
14317       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14318         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14319     }
14320     return;
14321   }
14322 }
14323
14324
14325
14326 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14327 {
14328   word Info;
14329   word internal_command;
14330
14331   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14332     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14333
14334   Info = GOOD;
14335   internal_command = plci->internal_command;
14336   plci->internal_command = 0;
14337   switch (internal_command)
14338   {
14339   default:
14340     plci->command = 0;
14341   case RTP_CONNECT_B3_REQ_COMMAND_1:
14342     if (plci_nl_busy (plci))
14343     {
14344       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14345       return;
14346     }
14347     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14348     nl_req_ncci (plci, N_CONNECT, 0);
14349     send_req (plci);
14350     return;
14351   case RTP_CONNECT_B3_REQ_COMMAND_2:
14352     if ((Rc != OK) && (Rc != OK_FC))
14353     {
14354       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14355         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14356       Info = _WRONG_STATE;
14357       break;
14358     }
14359     if (plci_nl_busy (plci))
14360     {
14361       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14362       return;
14363     }
14364     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14365     plci->NData[0].PLength = plci->internal_req_buffer[0];
14366     plci->NData[0].P = plci->internal_req_buffer + 1;
14367     plci->NL.X = plci->NData;
14368     plci->NL.ReqCh = 0;
14369     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14370     plci->adapter->request (&plci->NL);
14371     break;
14372   case RTP_CONNECT_B3_REQ_COMMAND_3:
14373     return;
14374   }
14375   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14376 }
14377
14378
14379 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14380 {
14381   word Info;
14382   word internal_command;
14383
14384   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14385     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14386
14387   Info = GOOD;
14388   internal_command = plci->internal_command;
14389   plci->internal_command = 0;
14390   switch (internal_command)
14391   {
14392   default:
14393     plci->command = 0;
14394   case RTP_CONNECT_B3_RES_COMMAND_1:
14395     if (plci_nl_busy (plci))
14396     {
14397       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14398       return;
14399     }
14400     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14401     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14402     send_req (plci);
14403     return;
14404   case RTP_CONNECT_B3_RES_COMMAND_2:
14405     if ((Rc != OK) && (Rc != OK_FC))
14406     {
14407       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14408         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14409       Info = _WRONG_STATE;
14410       break;
14411     }
14412     if (plci_nl_busy (plci))
14413     {
14414       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14415       return;
14416     }
14417     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14418     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14419     plci->NData[0].PLength = plci->internal_req_buffer[0];
14420     plci->NData[0].P = plci->internal_req_buffer + 1;
14421     plci->NL.X = plci->NData;
14422     plci->NL.ReqCh = 0;
14423     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14424     plci->adapter->request (&plci->NL);
14425     return;
14426   case RTP_CONNECT_B3_RES_COMMAND_3:
14427     return;
14428   }
14429 }
14430
14431
14432
14433 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14434 {
14435     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14436   word Info;
14437   word internal_command;
14438
14439   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14440     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14441
14442   Info = GOOD;
14443   internal_command = plci->internal_command;
14444   plci->internal_command = 0;
14445   switch (internal_command)
14446   {
14447   default:
14448     if (!plci->NL.Id)
14449       break;
14450     plci->command = 0;
14451     plci->adjust_b_parms_msg = NULL;
14452     plci->adjust_b_facilities = plci->B1_facilities;
14453     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14454     plci->adjust_b_ncci = (word)(Id >> 16);
14455     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14456     plci->adjust_b_state = ADJUST_B_START;
14457     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14458       UnMapId (Id), (char   *)(FILE_), __LINE__));
14459   case HOLD_SAVE_COMMAND_1:
14460     Info = adjust_b_process (Id, plci, Rc);
14461     if (Info != GOOD)
14462     {
14463       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14464         UnMapId (Id), (char   *)(FILE_), __LINE__));
14465       break;
14466     }
14467     if (plci->internal_command)
14468       return;
14469   }
14470   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14471 }
14472
14473
14474 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14475 {
14476     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14477   word Info;
14478   word internal_command;
14479
14480   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14481     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14482
14483   Info = GOOD;
14484   internal_command = plci->internal_command;
14485   plci->internal_command = 0;
14486   switch (internal_command)
14487   {
14488   default:
14489     plci->command = 0;
14490     plci->adjust_b_parms_msg = NULL;
14491     plci->adjust_b_facilities = plci->B1_facilities;
14492     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14493     plci->adjust_b_ncci = (word)(Id >> 16);
14494     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14495     plci->adjust_b_state = ADJUST_B_START;
14496     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14497       UnMapId (Id), (char   *)(FILE_), __LINE__));
14498   case RETRIEVE_RESTORE_COMMAND_1:
14499     Info = adjust_b_process (Id, plci, Rc);
14500     if (Info != GOOD)
14501     {
14502       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14503         UnMapId (Id), (char   *)(FILE_), __LINE__));
14504       break;
14505     }
14506     if (plci->internal_command)
14507       return;
14508   }
14509   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14510 }
14511
14512
14513 static void init_b1_config (PLCI   *plci)
14514 {
14515
14516   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14517     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14518     (char   *)(FILE_), __LINE__));
14519
14520   plci->B1_resource = 0;
14521   plci->B1_facilities = 0;
14522
14523   plci->li_bchannel_id = 0;
14524   mixer_clear_config (plci);
14525
14526
14527   ec_clear_config (plci);
14528
14529
14530   dtmf_rec_clear_config (plci);
14531   dtmf_send_clear_config (plci);
14532   dtmf_parameter_clear_config (plci);
14533
14534   adv_voice_clear_config (plci);
14535   adjust_b_clear (plci);
14536 }
14537
14538
14539 static void clear_b1_config (PLCI   *plci)
14540 {
14541
14542   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14543     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14544     (char   *)(FILE_), __LINE__));
14545
14546   adv_voice_clear_config (plci);
14547   adjust_b_clear (plci);
14548
14549   ec_clear_config (plci);
14550
14551
14552   dtmf_rec_clear_config (plci);
14553   dtmf_send_clear_config (plci);
14554   dtmf_parameter_clear_config (plci);
14555
14556
14557   if ((plci->li_bchannel_id != 0)
14558    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14559   {
14560     mixer_clear_config (plci);
14561     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14562     plci->li_bchannel_id = 0;
14563   }
14564
14565   plci->B1_resource = 0;
14566   plci->B1_facilities = 0;
14567 }
14568
14569
14570 /* -----------------------------------------------------------------
14571                 XON protocol local helpers
14572    ----------------------------------------------------------------- */
14573 static void channel_flow_control_remove (PLCI   * plci) {
14574   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14575   word i;
14576   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14577     if (a->ch_flow_plci[i] == plci->Id) {
14578       a->ch_flow_plci[i] = 0;
14579       a->ch_flow_control[i] = 0;
14580     }
14581   }
14582 }
14583
14584 static void channel_x_on (PLCI   * plci, byte ch) {
14585   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14586   if (a->ch_flow_control[ch] & N_XON_SENT) {
14587     a->ch_flow_control[ch] &= ~N_XON_SENT;
14588   }
14589 }
14590
14591 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14592   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14593   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14594     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14595     a->ch_flow_plci[ch] = plci->Id;
14596     a->ch_flow_control_pending++;
14597   }
14598 }
14599
14600 static void channel_request_xon (PLCI   * plci, byte ch) {
14601   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14602
14603   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14604     a->ch_flow_control[ch] |= N_XON_REQ;
14605     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14606     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14607   }
14608 }
14609
14610 static void channel_xmit_extended_xon (PLCI   * plci) {
14611   DIVA_CAPI_ADAPTER   * a;
14612   int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14613   int i, one_requested = 0;
14614
14615   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14616     return;
14617   }
14618
14619   for (i = 0; i < max_ch; i++) {
14620     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14621         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14622         (plci->Id == a->ch_flow_plci[i])) {
14623       channel_request_xon (plci, (byte)i);
14624       one_requested = 1;
14625     }
14626   }
14627
14628   if (one_requested) {
14629     channel_xmit_xon (plci);
14630   }
14631 }
14632
14633 /*
14634   Try to xmit next X_ON
14635   */
14636 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14637   int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14638   int i;
14639
14640   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14641     return (0);
14642   }
14643
14644   if (a->last_flow_control_ch >= max_ch) {
14645     a->last_flow_control_ch = 1;
14646   }
14647   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14648     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649         (plci->Id == a->ch_flow_plci[i])) {
14650       a->last_flow_control_ch = i+1;
14651       return (i);
14652     }
14653   }
14654
14655   for (i = 1; i < a->last_flow_control_ch; i++) {
14656     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14657         (plci->Id == a->ch_flow_plci[i])) {
14658       a->last_flow_control_ch = i+1;
14659       return (i);
14660     }
14661   }
14662
14663   return (0);
14664 }
14665
14666 static void channel_xmit_xon (PLCI   * plci) {
14667   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14668   byte ch;
14669
14670   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14671     return;
14672   }
14673   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14674     return;
14675   }
14676   a->ch_flow_control[ch] &= ~N_XON_REQ;
14677   a->ch_flow_control[ch] |= N_XON_SENT;
14678
14679   plci->NL.Req = plci->nl_req = (byte)N_XON;
14680   plci->NL.ReqCh         = ch;
14681   plci->NL.X             = plci->NData;
14682   plci->NL.XNum          = 1;
14683   plci->NData[0].P       = &plci->RBuffer[0];
14684   plci->NData[0].PLength = 0;
14685
14686   plci->adapter->request(&plci->NL);
14687 }
14688
14689 static int channel_can_xon (PLCI   * plci, byte ch) {
14690   APPL   * APPLptr;
14691   DIVA_CAPI_ADAPTER   * a;
14692   word NCCIcode;
14693   dword count;
14694   word Num;
14695   word i;
14696
14697   APPLptr = plci->appl;
14698   a = plci->adapter;
14699
14700   if (!APPLptr)
14701     return (0);
14702
14703   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14704
14705                 /* count all buffers within the Application pool    */
14706                 /* belonging to the same NCCI. XON if a first is    */
14707                 /* used.                                            */
14708   count = 0;
14709   Num = 0xffff;
14710   for(i=0; i<APPLptr->MaxBuffer; i++) {
14711     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14712     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14713   }
14714   if ((count > 2) || (Num == 0xffff)) {
14715     return (0);
14716   }
14717   return (1);
14718 }
14719
14720
14721 /*------------------------------------------------------------------*/
14722
14723 /* to be completed */
14724 void disable_adapter(byte adapter_number)
14725 {
14726   word j, ncci;
14727   DIVA_CAPI_ADAPTER   *a;
14728   PLCI   *plci;
14729   dword Id;
14730
14731   if ((adapter_number == 0) || (adapter_number > max_adapter) || !adapter[adapter_number-1].request)
14732   {
14733     dbug(1,dprintf("disable adapter: number %d invalid",adapter_number));
14734     return;
14735   }
14736   dbug(1,dprintf("disable adapter number %d",adapter_number));
14737     /* Capi20 starts with Nr. 1, internal field starts with 0 */
14738   a = &adapter[adapter_number-1];
14739   a->adapter_disabled = TRUE;
14740   for(j=0;j<a->max_plci;j++)
14741   {
14742     if(a->plci[j].Id) /* disconnect logical links */
14743     {
14744       plci = &a->plci[j];
14745       if(plci->channels)
14746       {
14747         for(ncci=1;ncci<MAX_NCCI+1 && plci->channels;ncci++)
14748         {
14749           if(a->ncci_plci[ncci]==plci->Id)
14750           {
14751             Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
14752             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"ws",0,"");
14753             plci->channels--;
14754           }
14755         }
14756       }
14757
14758       if(plci->State!=LISTENING) /* disconnect physical links */
14759       {
14760         Id = ((word)plci->Id<<8)|a->Id;
14761         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
14762         plci_remove(plci);
14763         plci->Sig.Id = 0;
14764         plci->NL.Id = 0;
14765         plci_remove(plci);
14766       }
14767     }
14768   }
14769 }
14770
14771 void enable_adapter(byte adapter_number)
14772 {
14773   DIVA_CAPI_ADAPTER   *a;
14774
14775   if ((adapter_number == 0) || (adapter_number > max_adapter) || !adapter[adapter_number-1].request)
14776   {
14777     dbug(1,dprintf("enable adapter: number %d invalid",adapter_number));
14778     return;
14779   }
14780   dbug(1,dprintf("enable adapter number %d",adapter_number));
14781     /* Capi20 starts with Nr. 1, internal field starts with 0 */
14782   a = &adapter[adapter_number-1];
14783   a->adapter_disabled = FALSE;
14784   listen_check(a);
14785 }
14786
14787
14788 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14789 {
14790   return 1;
14791 }
14792
14793
14794
14795 /**********************************************************************************/
14796 /* function groups the listening applications according to the CIP mask and the   */
14797 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14798 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14799 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14800 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14801 /* OS specific part (per adapter).                                                */
14802 /**********************************************************************************/
14803 void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14804 {
14805   word i,j,k,busy,group_found;
14806   dword info_mask_group[MAX_CIP_TYPES];
14807   dword cip_mask_group[MAX_CIP_TYPES];
14808   word appl_number_group_type[MAX_APPL];
14809   PLCI   *auxplci;
14810
14811   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14812
14813   if(!a->group_optimization_enabled)
14814   {
14815     dbug(1,dprintf("No group optimization"));
14816     return;
14817   }
14818
14819   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14820
14821   for(i=0;i<MAX_CIP_TYPES;i++)
14822   {
14823     info_mask_group[i] = 0;
14824     cip_mask_group [i] = 0;;
14825   }
14826   for(i=0;i<MAX_APPL;i++)
14827   {
14828     appl_number_group_type[i] = 0;
14829   }
14830   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14831   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14832     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14833     {
14834       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14835       return; /* allow good application unfiltered access */
14836     }
14837   }
14838   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14839   {
14840     if(application[i].Id && a->CIP_Mask[i] )
14841     {
14842       for(k=0,busy=FALSE; k<a->max_plci; k++)
14843       {
14844         if(a->plci[k].Id) 
14845         {
14846           auxplci = &a->plci[k];
14847           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14848           {
14849             busy = TRUE;
14850             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14851           }
14852           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14853           {
14854             busy = TRUE;
14855             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14856           }
14857         }
14858       }
14859
14860       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14861       {
14862         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14863         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14864           appl_number_group_type[i] = MAX_CIP_TYPES;
14865           group_found=TRUE;
14866           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14867         }
14868         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14869         {                                      /* is group already present ?                  */
14870           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14871           group_found=TRUE;
14872           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]));
14873         }
14874         else if(!info_mask_group[j])
14875         {                                      /* establish a new group                       */
14876           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14877           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14878           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14879           group_found=TRUE;
14880           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]));
14881         }
14882       }
14883     }
14884   }
14885         
14886   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14887   {
14888     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14889     {
14890       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14891       {
14892         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14893       }
14894       else
14895       {
14896         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14897         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14898         {
14899           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14900           {
14901             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14902             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14903             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14904           }
14905         }
14906       }
14907     }
14908     else                                                 /* application should not get a call */
14909     {
14910       clear_group_ind_mask_bit (plci, i);
14911     }
14912   }
14913
14914 }
14915
14916
14917
14918 /* OS notifies the driver about a application Capi_Register */
14919 word CapiRegister(word id)
14920 {
14921   word i,j,appls_found;
14922
14923   PLCI   *plci;
14924   DIVA_CAPI_ADAPTER   *a;
14925
14926   for(i=0,appls_found=0; i<max_appl; i++)
14927   {
14928     if( application[i].Id && (application[i].Id!=id) )
14929     {
14930       appls_found++;                       /* an application has been found */
14931     }
14932   }
14933
14934   if(appls_found) return TRUE;
14935   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14936   {
14937     a = &adapter[i];
14938     if(a->request)
14939     {
14940       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14941       {
14942         if(!appls_found)           /* first application does a capi register   */
14943         {
14944           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14945           {
14946             plci = &a->plci[j-1];
14947             plci->command = 0;
14948             add_p(plci,OAD,"\x01\xfd");
14949             add_p(plci,CAI,"\x01\x80");
14950             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14951             add_p(plci,SHIFT|6,0);
14952             add_p(plci,SIN,"\x02\x00\x00");
14953             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14954             sig_req(plci,ASSIGN,DSIG_ID);
14955             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14956             sig_req(plci,SIG_CTRL,0);
14957             send_req(plci);
14958           }
14959         }
14960       }
14961     }
14962   }
14963   return FALSE;
14964 }
14965
14966 /*------------------------------------------------------------------*/
14967
14968 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14969
14970 void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14971 {
14972  word i;
14973  /* Format of vswitch_t:
14974  0 byte length
14975  1 byte VSWITCHIE
14976  2 byte VSWITCH_REQ/VSWITCH_IND
14977  3 byte reserved
14978  4 word VSwitchcommand
14979  6 word returnerror
14980  8... Params
14981  */
14982  if(!plci ||
14983   !plci->appl ||
14984   !plci->State ||
14985   plci->Sig.Ind==NCR_FACILITY
14986   )
14987   return;
14988  
14989  for(i=0;i<MAX_MULTI_IE;i++)
14990  {
14991         if(!parms[i][0]) continue;
14992   if(parms[i][0]<7)
14993   {
14994    parms[i][0]=0; /* kill it */
14995    continue;
14996   }
14997   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14998   switch(parms[i][4])
14999   {
15000   case VSJOIN:
15001    if(!plci->relatedPTYPLCI ||
15002     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
15003    { /* Error */
15004     break;
15005    }
15006    /* remember all necessary informations */
15007    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
15008    {
15009     break;
15010    }
15011    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
15012    {   /* first indication after ECT-Request on Consultation Call */
15013     plci->vswitchstate=parms[i][9];
15014     parms[i][9]=2; /* State */
15015     /* now ask first Call to join */
15016    }
15017    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
15018    { /* Answer of VSWITCH_REQ from first Call */
15019     plci->vswitchstate=parms[i][9];
15020     /* tell consultation call to join
15021     and the protocol capabilities of the first call */
15022    }
15023    else
15024    { /* Error */
15025     break;
15026    }    
15027    plci->vsprot=parms[i][10]; /* protocol */
15028    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
15029    /* send join request to related PLCI */
15030    parms[i][1]=VSWITCHIE;
15031    parms[i][2]=VSWITCH_REQ;
15032    
15033    plci->relatedPTYPLCI->command = 0;
15034    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
15035    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
15036    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15037    send_req(plci->relatedPTYPLCI);
15038    break;
15039   case VSTRANSPORT:
15040   default:
15041    if(plci->relatedPTYPLCI &&
15042     plci->vswitchstate==3 &&
15043     plci->relatedPTYPLCI->vswitchstate==3)
15044    {
15045     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
15046     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15047     send_req(plci->relatedPTYPLCI);
15048    }
15049    break;
15050   }  
15051   parms[i][0]=0; /* kill it */
15052  }
15053 }
15054
15055
15056 /*------------------------------------------------------------------*/
15057
15058 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
15059   ENTITY e;
15060   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15061
15062   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15063     return (-1);
15064   }
15065
15066   pReq->xdi_dma_descriptor_operation.Req = 0;
15067   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15068
15069   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15070   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15071   pReq->xdi_dma_descriptor_operation.info.descriptor_address = 0;
15072   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15073
15074   e.user[0] = plci->adapter->Id - 1;
15075   plci->adapter->request((ENTITY*)pReq);
15076
15077   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15078       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15079       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15080     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15081     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15082          plci->adapter->Id,
15083          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15084          *dma_magic));
15085     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15086   } else {
15087     dbug(1,dprintf("dma_alloc failed"));
15088     return (-1);
15089   }
15090 }
15091
15092 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15093   ENTITY e;
15094   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15095
15096   if (nr < 0) {
15097     return;
15098   }
15099
15100   pReq->xdi_dma_descriptor_operation.Req = 0;
15101   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15102
15103   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15104   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15105   pReq->xdi_dma_descriptor_operation.info.descriptor_address = 0;
15106   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15107
15108   e.user[0] = plci->adapter->Id - 1;
15109   plci->adapter->request((ENTITY*)pReq);
15110
15111   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15112     dbug(1,dprintf("dma_free(%d)", nr));
15113   } else {
15114     dbug(1,dprintf("dma_free failed (%d)", nr));
15115   }
15116 }
15117
15118 /*------------------------------------------------------------------*/