Merge branches 'pm-cpufreq', 'pm-cpuidle', 'pm-devfreq', 'pm-opp' and 'pm-tools'
[linux-drm-fsl-dcu.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3  Copyright (c) Eicon Networks, 2002.
4  *
5  This source file is supplied for the use with
6  Eicon Networks range of DIVA Server Adapters.
7  *
8  Eicon File Revision :    2.1
9  *
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2, or (at your option)
13  any later version.
14  *
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  See the GNU General Public License for more details.
19  *
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67 */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
75 static void set_group_ind_mask(PLCI *plci);
76 static void clear_group_ind_mask_bit(PLCI *plci, word b);
77 static byte test_group_ind_mask_bit(PLCI *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL *, CAPI_MSG *);
82 static word api_parse(byte *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84 static void api_load_msg(API_SAVE *in, API_PARSE *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI *);
90 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
91 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
92
93 void callback(ENTITY *);
94
95 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI *, byte);
97 static void data_ack(PLCI *, byte);
98 static void sig_ind(PLCI *);
99 static void SendInfo(PLCI *, dword, byte **, byte);
100 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
101 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
102
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
104
105 static void nl_ind(PLCI *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER *);
133 static void add_p(PLCI *, byte, byte *);
134 static void add_s(PLCI *plci, byte code, API_PARSE *p);
135 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
136 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
137 static void add_d(PLCI *, word, byte *);
138 static void add_ai(PLCI *, API_PARSE *);
139 static word add_b1(PLCI *, API_PARSE *, word, word);
140 static word add_b23(PLCI *, API_PARSE *);
141 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
142 static void sig_req(PLCI *, byte, byte);
143 static void nl_req_ncci(PLCI *, byte, byte);
144 static void send_req(PLCI *);
145 static void send_data(PLCI *);
146 static word plci_remove_check(PLCI *);
147 static void listen_check(DIVA_CAPI_ADAPTER *);
148 static byte AddInfo(byte **, byte **, byte *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI *, word *, byte **, byte);
151 static byte ie_compare(byte *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
154
155 /*
156   XON protocol helpers
157 */
158 static void channel_flow_control_remove(PLCI *plci);
159 static void channel_x_off(PLCI *plci, byte ch, byte flag);
160 static void channel_x_on(PLCI *plci, byte ch);
161 static void channel_request_xon(PLCI *plci, byte ch);
162 static void channel_xmit_xon(PLCI *plci);
163 static int channel_can_xon(PLCI *plci, byte ch);
164 static void channel_xmit_extended_xon(PLCI *plci);
165
166 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
170 static void VoiceChannelOff(PLCI *plci);
171 static void adv_voice_write_coefs(PLCI *plci, word write_command);
172 static void adv_voice_clear_config(PLCI *plci);
173
174 static word get_b1_facilities(PLCI *plci, byte b1_resource);
175 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
178 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
180 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
181 static void select_b_command(dword Id, PLCI *plci, byte Rc);
182 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
183 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
185 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
186 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
187 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
188 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
189 static void init_b1_config(PLCI *plci);
190 static void clear_b1_config(PLCI *plci);
191
192 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
193 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194 static void dtmf_confirmation(dword Id, PLCI *plci);
195 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
196 static void dtmf_parameter_write(PLCI *plci);
197
198
199 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
201 static void mixer_clear_config(PLCI *plci);
202 static void mixer_notify_update(PLCI *plci, byte others);
203 static void mixer_command(dword Id, PLCI *plci, byte Rc);
204 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
206 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
207 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_remove(PLCI *plci);
209
210
211 static void ec_command(dword Id, PLCI *plci, byte Rc);
212 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
214
215
216 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
217 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
218
219
220 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor(PLCI *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController(byte);
228 extern byte UnMapController(byte);
229 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
230 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
231
232 void sendf(APPL *, word, dword, word, byte *, ...);
233 void *TransmitBufferSet(APPL *appl, dword ref);
234 void *TransmitBufferGet(APPL *appl, void *p);
235 void TransmitBufferFree(APPL *appl, void *p);
236 void *ReceiveBufferGet(APPL *appl, int Num);
237
238 int fax_head_line_time(char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER *adapter;
247 extern APPL *application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260         word command;
261         byte *format;
262         byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
263 } ftable[] = {
264         {_DATA_B3_R,                          "dwww",         data_b3_req},
265         {_DATA_B3_I | RESPONSE,               "w",            data_b3_res},
266         {_INFO_R,                             "ss",           info_req},
267         {_INFO_I | RESPONSE,                  "",             info_res},
268         {_CONNECT_R,                          "wsssssssss",   connect_req},
269         {_CONNECT_I | RESPONSE,               "wsssss",       connect_res},
270         {_CONNECT_ACTIVE_I | RESPONSE,        "",             connect_a_res},
271         {_DISCONNECT_R,                       "s",            disconnect_req},
272         {_DISCONNECT_I | RESPONSE,            "",             disconnect_res},
273         {_LISTEN_R,                           "dddss",        listen_req},
274         {_ALERT_R,                            "s",            alert_req},
275         {_FACILITY_R,                         "ws",           facility_req},
276         {_FACILITY_I | RESPONSE,              "ws",           facility_res},
277         {_CONNECT_B3_R,                       "s",            connect_b3_req},
278         {_CONNECT_B3_I | RESPONSE,            "ws",           connect_b3_res},
279         {_CONNECT_B3_ACTIVE_I | RESPONSE,     "",             connect_b3_a_res},
280         {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281         {_DISCONNECT_B3_I | RESPONSE,         "",             disconnect_b3_res},
282         {_RESET_B3_R,                         "s",            reset_b3_req},
283         {_RESET_B3_I | RESPONSE,              "",             reset_b3_res},
284         {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws",           connect_b3_t90_a_res},
285         {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "",             connect_b3_t90_a_res},
286         {_SELECT_B_REQ,                       "s",            select_b_req},
287         {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288         {_MANUFACTURER_I | RESPONSE,          "dws",          manufacturer_res},
289         {_MANUFACTURER_I | RESPONSE,          "",             manufacturer_res}
290 };
291
292 static byte *cip_bc[29][2] = {
293         { "",                     ""                     }, /* 0 */
294         { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296         { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297         { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299         { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300         { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301         { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303         { "",                     ""                     }, /* 10 */
304         { "",                     ""                     }, /* 11 */
305         { "",                     ""                     }, /* 12 */
306         { "",                     ""                     }, /* 13 */
307         { "",                     ""                     }, /* 14 */
308         { "",                     ""                     }, /* 15 */
309
310         { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311         { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322         { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte *cip_hlc[29] = {
326         "",                           /* 0 */
327         "",                           /* 1 */
328         "",                           /* 2 */
329         "",                           /* 3 */
330         "",                           /* 4 */
331         "",                           /* 5 */
332         "",                           /* 6 */
333         "",                           /* 7 */
334         "",                           /* 8 */
335         "",                           /* 9 */
336         "",                           /* 10 */
337         "",                           /* 11 */
338         "",                           /* 12 */
339         "",                           /* 13 */
340         "",                           /* 14 */
341         "",                           /* 15 */
342
343         "\x02\x91\x81",               /* 16 */
344         "\x02\x91\x84",               /* 17 */
345         "\x02\x91\xa1",               /* 18 */
346         "\x02\x91\xa4",               /* 19 */
347         "\x02\x91\xa8",               /* 20 */
348         "\x02\x91\xb1",               /* 21 */
349         "\x02\x91\xb2",               /* 22 */
350         "\x02\x91\xb5",               /* 23 */
351         "\x02\x91\xb8",               /* 24 */
352         "\x02\x91\xc1",               /* 25 */
353         "\x02\x91\x81",               /* 26 */
354         "\x03\x91\xe0\x01",           /* 27 */
355         "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370         0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377         0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL *appl, CAPI_MSG *msg)
387 {
388         word i, j, k, l, n;
389         word ret;
390         byte c;
391         byte controller;
392         DIVA_CAPI_ADAPTER *a;
393         PLCI *plci;
394         NCCI *ncci_ptr;
395         word ncci;
396         CAPI_MSG *m;
397         API_PARSE msg_parms[MAX_MSG_PARMS + 1];
398
399         if (msg->header.length < sizeof(msg->header) ||
400             msg->header.length > MAX_MSG_SIZE) {
401                 dbug(1, dprintf("bad len"));
402                 return _BAD_MSG;
403         }
404
405         controller = (byte)((msg->header.controller & 0x7f) - 1);
406
407         /* controller starts with 0 up to (max_adapter - 1) */
408         if (controller >= max_adapter)
409         {
410                 dbug(1, dprintf("invalid ctrl"));
411                 return _BAD_MSG;
412         }
413
414         a = &adapter[controller];
415         plci = NULL;
416         if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417         {
418                 dbug(1, dprintf("plci=%x", msg->header.plci));
419                 plci = &a->plci[msg->header.plci - 1];
420                 ncci = GET_WORD(&msg->header.ncci);
421                 if (plci->Id
422                     && (plci->appl
423                         || (plci->State == INC_CON_PENDING)
424                         || (plci->State == INC_CON_ALERT)
425                         || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
426                     && ((ncci == 0)
427                         || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
428                         || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
429                 {
430                         i = plci->msg_in_read_pos;
431                         j = plci->msg_in_write_pos;
432                         if (j >= i)
433                         {
434                                 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435                                         i += MSG_IN_QUEUE_SIZE - j;
436                                 else
437                                         j = 0;
438                         }
439                         else
440                         {
441
442                                 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444                                 if (i > MSG_IN_QUEUE_SIZE - n)
445                                         i = MSG_IN_QUEUE_SIZE - n + 1;
446                                 i -= j;
447                         }
448
449                         if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451                         {
452                                 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453                                                 msg->header.length, plci->msg_in_write_pos,
454                                                 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456                                 return _QUEUE_FULL;
457                         }
458                         c = false;
459                         if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460                             || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461                         {
462                                 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463                                         c = true;
464                         }
465                         if (msg->header.command == _DATA_B3_R)
466                         {
467                                 if (msg->header.length < 20)
468                                 {
469                                         dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470                                         return _BAD_MSG;
471                                 }
472                                 ncci_ptr = &(a->ncci[ncci]);
473                                 n = ncci_ptr->data_pending;
474                                 l = ncci_ptr->data_ack_pending;
475                                 k = plci->msg_in_read_pos;
476                                 while (k != plci->msg_in_write_pos)
477                                 {
478                                         if (k == plci->msg_in_wrap_pos)
479                                                 k = 0;
480                                         if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481                                             && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482                                         {
483                                                 n++;
484                                                 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485                                                         l++;
486                                         }
487
488                                         k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489                                               MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491                                 }
492                                 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493                                 {
494                                         dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                                                         ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497                                         return _QUEUE_FULL;
498                                 }
499                                 if (plci->req_in || plci->internal_command)
500                                 {
501                                         if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502                                             && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503                                         {
504                                                 dbug(0, dprintf("Q-FULL3(requeue)"));
505
506                                                 return _QUEUE_FULL;
507                                         }
508                                         c = true;
509                                 }
510                         }
511                         else
512                         {
513                                 if (plci->req_in || plci->internal_command)
514                                         c = true;
515                                 else
516                                 {
517                                         plci->command = msg->header.command;
518                                         plci->number = msg->header.number;
519                                 }
520                         }
521                         if (c)
522                         {
523                                 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524                                                 msg->header.command, plci->req_in, plci->internal_command,
525                                                 msg->header.length, plci->msg_in_write_pos,
526                                                 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527                                 if (j == 0)
528                                         plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529                                 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530                                 for (i = 0; i < msg->header.length; i++)
531                                         ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532                                 if (m->header.command == _DATA_B3_R)
533                                 {
534
535                                         m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
536
537                                 }
538
539                                 j = (j + 3) & 0xfffc;
540
541                                 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542                                 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543                                 return 0;
544                         }
545                 }
546                 else
547                 {
548                         plci = NULL;
549                 }
550         }
551         dbug(1, dprintf("com=%x", msg->header.command));
552
553         for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
554         for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
555
556                 if (ftable[i].command == msg->header.command) {
557                         /* break loop if the message is correct, otherwise continue scan  */
558                         /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
559                         if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
560                                 ret = 0;
561                                 break;
562                         }
563                         for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
564                 }
565         }
566         if (ret) {
567                 dbug(1, dprintf("BAD_MSG"));
568                 if (plci) plci->command = 0;
569                 return ret;
570         }
571
572
573         c = ftable[i].function(GET_DWORD(&msg->header.controller),
574                                msg->header.number,
575                                a,
576                                plci,
577                                appl,
578                                msg_parms);
579
580         channel_xmit_extended_xon(plci);
581
582         if (c == 1) send_req(plci);
583         if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584         if (plci && !plci->req_in) plci->command = 0;
585         return 0;
586 }
587
588
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages             */
591 /*------------------------------------------------------------------*/
592
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
594 {
595         word i;
596         word p;
597
598         for (i = 0, p = 0; format[i]; i++) {
599                 if (parms)
600                 {
601                         parms[i].info = &msg[p];
602                 }
603                 switch (format[i]) {
604                 case 'b':
605                         p += 1;
606                         break;
607                 case 'w':
608                         p += 2;
609                         break;
610                 case 'd':
611                         p += 4;
612                         break;
613                 case 's':
614                         if (msg[p] == 0xff) {
615                                 parms[i].info += 2;
616                                 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
617                                 p += (parms[i].length + 3);
618                         }
619                         else {
620                                 parms[i].length = msg[p];
621                                 p += (parms[i].length + 1);
622                         }
623                         break;
624                 }
625
626                 if (p > length) return true;
627         }
628         if (parms) parms[i].info = NULL;
629         return false;
630 }
631
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
633 {
634         word i, j, n = 0;
635         byte *p;
636
637         p = out->info;
638         for (i = 0; format[i] != '\0'; i++)
639         {
640                 out->parms[i].info = p;
641                 out->parms[i].length = in[i].length;
642                 switch (format[i])
643                 {
644                 case 'b':
645                         n = 1;
646                         break;
647                 case 'w':
648                         n = 2;
649                         break;
650                 case 'd':
651                         n = 4;
652                         break;
653                 case 's':
654                         n = in[i].length + 1;
655                         break;
656                 }
657                 for (j = 0; j < n; j++)
658                         *(p++) = in[i].info[j];
659         }
660         out->parms[i].info = NULL;
661         out->parms[i].length = 0;
662 }
663
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
665 {
666         word i;
667
668         i = 0;
669         do
670         {
671                 out[i].info = in->parms[i].info;
672                 out[i].length = in->parms[i].length;
673         } while (in->parms[i++].info);
674 }
675
676
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function                                             */
679 /*------------------------------------------------------------------*/
680
681 word api_remove_start(void)
682 {
683         word i;
684         word j;
685
686         if (!remove_started) {
687                 remove_started = true;
688                 for (i = 0; i < max_adapter; i++) {
689                         if (adapter[i].request) {
690                                 for (j = 0; j < adapter[i].max_plci; j++) {
691                                         if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692                                 }
693                         }
694                 }
695                 return 1;
696         }
697         else {
698                 for (i = 0; i < max_adapter; i++) {
699                         if (adapter[i].request) {
700                                 for (j = 0; j < adapter[i].max_plci; j++) {
701                                         if (adapter[i].plci[j].Sig.Id) return 1;
702                                 }
703                         }
704                 }
705         }
706         api_remove_complete();
707         return 0;
708 }
709
710
711 /*------------------------------------------------------------------*/
712 /* internal command queue                                           */
713 /*------------------------------------------------------------------*/
714
715 static void init_internal_command_queue(PLCI *plci)
716 {
717         word i;
718
719         dbug(1, dprintf("%s,%d: init_internal_command_queue",
720                         (char *)(FILE_), __LINE__));
721
722         plci->internal_command = 0;
723         for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724                 plci->internal_command_queue[i] = NULL;
725 }
726
727
728 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
729 {
730         word i;
731
732         dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733                         UnMapId(Id), (char *)(FILE_), __LINE__));
734
735         if (plci->internal_command == 0)
736         {
737                 plci->internal_command_queue[0] = command_function;
738                 (*command_function)(Id, plci, OK);
739         }
740         else
741         {
742                 i = 1;
743                 while (plci->internal_command_queue[i] != NULL)
744                         i++;
745                 plci->internal_command_queue[i] = command_function;
746         }
747 }
748
749
750 static void next_internal_command(dword Id, PLCI *plci)
751 {
752         word i;
753
754         dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755                         UnMapId(Id), (char *)(FILE_), __LINE__));
756
757         plci->internal_command = 0;
758         plci->internal_command_queue[0] = NULL;
759         while (plci->internal_command_queue[1] != NULL)
760         {
761                 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762                         plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
763                 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764                 (*(plci->internal_command_queue[0]))(Id, plci, OK);
765                 if (plci->internal_command != 0)
766                         return;
767                 plci->internal_command_queue[0] = NULL;
768         }
769 }
770
771
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function                                    */
774 /*------------------------------------------------------------------*/
775
776 static dword ncci_mapping_bug = 0;
777
778 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
779 {
780         DIVA_CAPI_ADAPTER *a;
781         word ncci, i, j, k;
782
783         a = plci->adapter;
784         if (!ch || a->ch_ncci[ch])
785         {
786                 ncci_mapping_bug++;
787                 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788                                 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789                 ncci = ch;
790         }
791         else
792         {
793                 if (force_ncci)
794                         ncci = force_ncci;
795                 else
796                 {
797                         if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
798                                 ncci = ch;
799                         else
800                         {
801                                 ncci = 1;
802                                 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
803                                         ncci++;
804                                 if (ncci == MAX_NCCI + 1)
805                                 {
806                                         ncci_mapping_bug++;
807                                         i = 1;
808                                         do
809                                         {
810                                                 j = 1;
811                                                 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
812                                                         j++;
813                                                 k = j;
814                                                 if (j < MAX_NCCI + 1)
815                                                 {
816                                                         do
817                                                         {
818                                                                 j++;
819                                                         } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
820                                                 }
821                                         } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
822                                         if (i < MAX_NL_CHANNEL + 1)
823                                         {
824                                                 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825                                                                 ncci_mapping_bug, ch, force_ncci, i, k, j));
826                                         }
827                                         else
828                                         {
829                                                 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830                                                                 ncci_mapping_bug, ch, force_ncci));
831                                         }
832                                         ncci = ch;
833                                 }
834                         }
835                         a->ncci_plci[ncci] = plci->Id;
836                         a->ncci_state[ncci] = IDLE;
837                         if (!plci->ncci_ring_list)
838                                 plci->ncci_ring_list = ncci;
839                         else
840                                 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841                         a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842                 }
843                 a->ncci_ch[ncci] = ch;
844                 a->ch_ncci[ch] = (byte) ncci;
845                 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846                                 ncci_mapping_bug, ch, force_ncci, ch, ncci));
847         }
848         return (ncci);
849 }
850
851
852 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
853 {
854         DIVA_CAPI_ADAPTER *a;
855         APPL *appl;
856         word i, ncci_code;
857         dword Id;
858
859         a = plci->adapter;
860         Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861         if (ncci)
862         {
863                 if (a->ncci_plci[ncci] == plci->Id)
864                 {
865                         if (!plci->appl)
866                         {
867                                 ncci_mapping_bug++;
868                                 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869                                                 ncci_mapping_bug, Id));
870                         }
871                         else
872                         {
873                                 appl = plci->appl;
874                                 ncci_code = ncci | (((word) a->Id) << 8);
875                                 for (i = 0; i < appl->MaxBuffer; i++)
876                                 {
877                                         if ((appl->DataNCCI[i] == ncci_code)
878                                             && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879                                         {
880                                                 appl->DataNCCI[i] = 0;
881                                         }
882                                 }
883                         }
884                 }
885         }
886         else
887         {
888                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
889                 {
890                         if (a->ncci_plci[ncci] == plci->Id)
891                         {
892                                 if (!plci->appl)
893                                 {
894                                         ncci_mapping_bug++;
895                                         dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896                                                         ncci_mapping_bug, Id));
897                                 }
898                                 else
899                                 {
900                                         appl = plci->appl;
901                                         ncci_code = ncci | (((word) a->Id) << 8);
902                                         for (i = 0; i < appl->MaxBuffer; i++)
903                                         {
904                                                 if ((appl->DataNCCI[i] == ncci_code)
905                                                     && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906                                                 {
907                                                         appl->DataNCCI[i] = 0;
908                                                 }
909                                         }
910                                 }
911                         }
912                 }
913         }
914 }
915
916
917 static void cleanup_ncci_data(PLCI *plci, word ncci)
918 {
919         NCCI *ncci_ptr;
920
921         if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922         {
923                 ncci_ptr = &(plci->adapter->ncci[ncci]);
924                 if (plci->appl)
925                 {
926                         while (ncci_ptr->data_pending != 0)
927                         {
928                                 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929                                         TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930                                 (ncci_ptr->data_out)++;
931                                 if (ncci_ptr->data_out == MAX_DATA_B3)
932                                         ncci_ptr->data_out = 0;
933                                 (ncci_ptr->data_pending)--;
934                         }
935                 }
936                 ncci_ptr->data_out = 0;
937                 ncci_ptr->data_pending = 0;
938                 ncci_ptr->data_ack_out = 0;
939                 ncci_ptr->data_ack_pending = 0;
940         }
941 }
942
943
944 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
945 {
946         DIVA_CAPI_ADAPTER *a;
947         dword Id;
948         word i;
949
950         a = plci->adapter;
951         Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952         if (!preserve_ncci)
953                 ncci_free_receive_buffers(plci, ncci);
954         if (ncci)
955         {
956                 if (a->ncci_plci[ncci] != plci->Id)
957                 {
958                         ncci_mapping_bug++;
959                         dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960                                         ncci_mapping_bug, Id, preserve_ncci));
961                 }
962                 else
963                 {
964                         cleanup_ncci_data(plci, ncci);
965                         dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966                                         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967                         a->ch_ncci[a->ncci_ch[ncci]] = 0;
968                         if (!preserve_ncci)
969                         {
970                                 a->ncci_ch[ncci] = 0;
971                                 a->ncci_plci[ncci] = 0;
972                                 a->ncci_state[ncci] = IDLE;
973                                 i = plci->ncci_ring_list;
974                                 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975                                         i = a->ncci_next[i];
976                                 if ((i != 0) && (a->ncci_next[i] == ncci))
977                                 {
978                                         if (i == ncci)
979                                                 plci->ncci_ring_list = 0;
980                                         else if (plci->ncci_ring_list == ncci)
981                                                 plci->ncci_ring_list = i;
982                                         a->ncci_next[i] = a->ncci_next[ncci];
983                                 }
984                                 a->ncci_next[ncci] = 0;
985                         }
986                 }
987         }
988         else
989         {
990                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
991                 {
992                         if (a->ncci_plci[ncci] == plci->Id)
993                         {
994                                 cleanup_ncci_data(plci, ncci);
995                                 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996                                                 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997                                 a->ch_ncci[a->ncci_ch[ncci]] = 0;
998                                 if (!preserve_ncci)
999                                 {
1000                                         a->ncci_ch[ncci] = 0;
1001                                         a->ncci_plci[ncci] = 0;
1002                                         a->ncci_state[ncci] = IDLE;
1003                                         a->ncci_next[ncci] = 0;
1004                                 }
1005                         }
1006                 }
1007                 if (!preserve_ncci)
1008                         plci->ncci_ring_list = 0;
1009         }
1010 }
1011
1012
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function                                             */
1015 /*------------------------------------------------------------------*/
1016
1017 static void plci_free_msg_in_queue(PLCI *plci)
1018 {
1019         word i;
1020
1021         if (plci->appl)
1022         {
1023                 i = plci->msg_in_read_pos;
1024                 while (i != plci->msg_in_write_pos)
1025                 {
1026                         if (i == plci->msg_in_wrap_pos)
1027                                 i = 0;
1028                         if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029                         {
1030
1031                                 TransmitBufferFree(plci->appl,
1032                                                    (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033
1034                         }
1035
1036                         i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037                               MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039                 }
1040         }
1041         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044 }
1045
1046
1047 static void plci_remove(PLCI *plci)
1048 {
1049
1050         if (!plci) {
1051                 dbug(1, dprintf("plci_remove(no plci)"));
1052                 return;
1053         }
1054         init_internal_command_queue(plci);
1055         dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056         if (plci_remove_check(plci))
1057         {
1058                 return;
1059         }
1060         if (plci->Sig.Id == 0xff)
1061         {
1062                 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063                 if (plci->NL.Id && !plci->nl_remove_id)
1064                 {
1065                         nl_req_ncci(plci, REMOVE, 0);
1066                         send_req(plci);
1067                 }
1068         }
1069         else
1070         {
1071                 if (!plci->sig_remove_id
1072                     && (plci->Sig.Id
1073                         || (plci->req_in != plci->req_out)
1074                         || (plci->nl_req || plci->sig_req)))
1075                 {
1076                         sig_req(plci, HANGUP, 0);
1077                         send_req(plci);
1078                 }
1079         }
1080         ncci_remove(plci, 0, false);
1081         plci_free_msg_in_queue(plci);
1082
1083         plci->channels = 0;
1084         plci->appl = NULL;
1085         if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086                 plci->State = OUTG_DIS_PENDING;
1087 }
1088
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers                               */
1091 /*------------------------------------------------------------------*/
1092
1093 static void set_group_ind_mask(PLCI *plci)
1094 {
1095         word i;
1096
1097         for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098                 plci->group_optimization_mask_table[i] = 0xffffffffL;
1099 }
1100
1101 static void clear_group_ind_mask_bit(PLCI *plci, word b)
1102 {
1103         plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104 }
1105
1106 static byte test_group_ind_mask_bit(PLCI *plci, word b)
1107 {
1108         return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109 }
1110
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1113 /*------------------------------------------------------------------*/
1114
1115 static void clear_c_ind_mask(PLCI *plci)
1116 {
1117         word i;
1118
1119         for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120                 plci->c_ind_mask_table[i] = 0;
1121 }
1122
1123 static byte c_ind_mask_empty(PLCI *plci)
1124 {
1125         word i;
1126
1127         i = 0;
1128         while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129                 i++;
1130         return (i == C_IND_MASK_DWORDS);
1131 }
1132
1133 static void set_c_ind_mask_bit(PLCI *plci, word b)
1134 {
1135         plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136 }
1137
1138 static void clear_c_ind_mask_bit(PLCI *plci, word b)
1139 {
1140         plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141 }
1142
1143 static byte test_c_ind_mask_bit(PLCI *plci, word b)
1144 {
1145         return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146 }
1147
1148 static void dump_c_ind_mask(PLCI *plci)
1149 {
1150         static char hex_digit_table[0x10] =
1151                 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1152         word i, j, k;
1153         dword d;
1154         char *p;
1155         char buf[40];
1156
1157         for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158         {
1159                 p = buf + 36;
1160                 *p = '\0';
1161                 for (j = 0; j < 4; j++)
1162                 {
1163                         if (i + j < C_IND_MASK_DWORDS)
1164                         {
1165                                 d = plci->c_ind_mask_table[i + j];
1166                                 for (k = 0; k < 8; k++)
1167                                 {
1168                                         *(--p) = hex_digit_table[d & 0xf];
1169                                         d >>= 4;
1170                                 }
1171                         }
1172                         else if (i != 0)
1173                         {
1174                                 for (k = 0; k < 8; k++)
1175                                         *(--p) = ' ';
1176                         }
1177                         *(--p) = ' ';
1178                 }
1179                 dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1180         }
1181 }
1182
1183
1184
1185
1186
1187 #define dump_plcis(a)
1188
1189
1190
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message                            */
1193 /*------------------------------------------------------------------*/
1194
1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196                         PLCI *plci, APPL *appl, API_PARSE *parms)
1197 {
1198         word ch;
1199         word i;
1200         word Info;
1201         byte LinkLayer;
1202         API_PARSE *ai;
1203         API_PARSE *bp;
1204         API_PARSE ai_parms[5];
1205         word channel = 0;
1206         dword ch_mask;
1207         byte m;
1208         static byte esc_chi[35] = {0x02, 0x18, 0x01};
1209         static byte lli[2] = {0x01, 0x00};
1210         byte noCh = 0;
1211         word dir = 0;
1212         byte *p_chi = "";
1213
1214         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1215
1216         dbug(1, dprintf("connect_req(%d)", parms->length));
1217         Info = _WRONG_IDENTIFIER;
1218         if (a)
1219         {
1220                 if (a->adapter_disabled)
1221                 {
1222                         dbug(1, dprintf("adapter disabled"));
1223                         Id = ((word)1 << 8) | a->Id;
1224                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1225                         sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1226                         return false;
1227                 }
1228                 Info = _OUT_OF_PLCI;
1229                 if ((i = get_plci(a)))
1230                 {
1231                         Info = 0;
1232                         plci = &a->plci[i - 1];
1233                         plci->appl = appl;
1234                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1235                         /* check 'external controller' bit for codec support */
1236                         if (Id & EXT_CONTROLLER)
1237                         {
1238                                 if (AdvCodecSupport(a, plci, appl, 0))
1239                                 {
1240                                         plci->Id = 0;
1241                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1242                                         return 2;
1243                                 }
1244                         }
1245                         ai = &parms[9];
1246                         bp = &parms[5];
1247                         ch = 0;
1248                         if (bp->length)LinkLayer = bp->info[3];
1249                         else LinkLayer = 0;
1250                         if (ai->length)
1251                         {
1252                                 ch = 0xffff;
1253                                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1254                                 {
1255                                         ch = 0;
1256                                         if (ai_parms[0].length)
1257                                         {
1258                                                 ch = GET_WORD(ai_parms[0].info + 1);
1259                                                 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1260                                                 if (ch == 4) /* explizit CHI in message */
1261                                                 {
1262                                                         /* check length of B-CH struct */
1263                                                         if ((ai_parms[0].info)[3] >= 1)
1264                                                         {
1265                                                                 if ((ai_parms[0].info)[4] == CHI)
1266                                                                 {
1267                                                                         p_chi = &((ai_parms[0].info)[5]);
1268                                                                 }
1269                                                                 else
1270                                                                 {
1271                                                                         p_chi = &((ai_parms[0].info)[3]);
1272                                                                 }
1273                                                                 if (p_chi[0] > 35) /* check length of channel ID */
1274                                                                 {
1275                                                                         Info = _WRONG_MESSAGE_FORMAT;
1276                                                                 }
1277                                                         }
1278                                                         else Info = _WRONG_MESSAGE_FORMAT;
1279                                                 }
1280
1281                                                 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1282                                                 {
1283                                                         dir = GET_WORD(ai_parms[0].info + 3);
1284                                                         ch_mask = 0;
1285                                                         m = 0x3f;
1286                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1287                                                         {
1288                                                                 if (ai_parms[0].info[i + 5] != 0)
1289                                                                 {
1290                                                                         if ((ai_parms[0].info[i + 5] | m) != 0xff)
1291                                                                                 Info = _WRONG_MESSAGE_FORMAT;
1292                                                                         else
1293                                                                         {
1294                                                                                 if (ch_mask == 0)
1295                                                                                         channel = i;
1296                                                                                 ch_mask |= 1L << i;
1297                                                                         }
1298                                                                 }
1299                                                                 m = 0;
1300                                                         }
1301                                                         if (ch_mask == 0)
1302                                                                 Info = _WRONG_MESSAGE_FORMAT;
1303                                                         if (!Info)
1304                                                         {
1305                                                                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1306                                                                 {
1307                                                                         esc_chi[0] = (byte)(ai_parms[0].length - 2);
1308                                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1309                                                                                 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1310                                                                 }
1311                                                                 else
1312                                                                         esc_chi[0] = 2;
1313                                                                 esc_chi[2] = (byte)channel;
1314                                                                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1315                                                                 add_p(plci, LLI, lli);
1316                                                                 add_p(plci, ESC, esc_chi);
1317                                                                 plci->State = LOCAL_CONNECT;
1318                                                                 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1319                                                         }
1320                                                 }
1321                                         }
1322                                 }
1323                                 else  Info = _WRONG_MESSAGE_FORMAT;
1324                         }
1325
1326                         dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1327                         plci->command = _CONNECT_R;
1328                         plci->number = Number;
1329                         /* x.31 or D-ch free SAPI in LinkLayer? */
1330                         if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1331                         if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1332                         {
1333                                 /* B-channel used for B3 connections (ch==0), or no B channel    */
1334                                 /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1335                                 if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1336                                 else     Info = add_b1(plci, &parms[5], ch, 0);
1337                                 add_s(plci, OAD, &parms[2]);
1338                                 add_s(plci, OSA, &parms[4]);
1339                                 add_s(plci, BC, &parms[6]);
1340                                 add_s(plci, LLC, &parms[7]);
1341                                 add_s(plci, HLC, &parms[8]);
1342                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1343                                 {
1344                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1345                                         add_p(plci, LLI, "\x01\x01");
1346                                 }
1347                                 if (GET_WORD(parms[0].info) < 29) {
1348                                         add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1349                                         add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1350                                 }
1351                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1352                                 sig_req(plci, ASSIGN, DSIG_ID);
1353                         }
1354                         else if (ch == 1) {
1355
1356                                 /* D-Channel used for B3 connections */
1357                                 plci->Sig.Id = 0xff;
1358                                 Info = 0;
1359                         }
1360
1361                         if (!Info && ch != 2 && !noCh) {
1362                                 Info = add_b23(plci, &parms[5]);
1363                                 if (!Info) {
1364                                         if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1365                                 }
1366                         }
1367
1368                         if (!Info)
1369                         {
1370                                 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1371                                 {
1372                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1373                                         {
1374                                                 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1375                                                 plci->spoofed_msg = CALL_REQ;
1376                                                 plci->internal_command = BLOCK_PLCI;
1377                                                 plci->command = 0;
1378                                                 dbug(1, dprintf("Spoof"));
1379                                                 send_req(plci);
1380                                                 return false;
1381                                         }
1382                                         if (ch == 4)add_p(plci, CHI, p_chi);
1383                                         add_s(plci, CPN, &parms[1]);
1384                                         add_s(plci, DSA, &parms[3]);
1385                                         if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1386                                         add_ai(plci, &parms[9]);
1387                                         if (!dir)sig_req(plci, CALL_REQ, 0);
1388                                         else
1389                                         {
1390                                                 plci->command = PERM_LIST_REQ;
1391                                                 plci->appl = appl;
1392                                                 sig_req(plci, LISTEN_REQ, 0);
1393                                                 send_req(plci);
1394                                                 return false;
1395                                         }
1396                                 }
1397                                 send_req(plci);
1398                                 return false;
1399                         }
1400                         plci->Id = 0;
1401                 }
1402         }
1403         sendf(appl,
1404               _CONNECT_R | CONFIRM,
1405               Id,
1406               Number,
1407               "w", Info);
1408         return 2;
1409 }
1410
1411 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1412                         PLCI *plci, APPL *appl, API_PARSE *parms)
1413 {
1414         word i, Info;
1415         word Reject;
1416         static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1417         static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1418         API_PARSE *ai;
1419         API_PARSE ai_parms[5];
1420         word ch = 0;
1421
1422         if (!plci) {
1423                 dbug(1, dprintf("connect_res(no plci)"));
1424                 return 0;  /* no plci, no send */
1425         }
1426
1427         dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1428         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1429         ai = &parms[5];
1430         dbug(1, dprintf("ai->length=%d", ai->length));
1431
1432         if (ai->length)
1433         {
1434                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1435                 {
1436                         dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1437                         ch = 0;
1438                         if (ai_parms[0].length)
1439                         {
1440                                 ch = GET_WORD(ai_parms[0].info + 1);
1441                                 dbug(1, dprintf("BCH-I=0x%x", ch));
1442                         }
1443                 }
1444         }
1445
1446         if (plci->State == INC_CON_CONNECTED_ALERT)
1447         {
1448                 dbug(1, dprintf("Connected Alert Call_Res"));
1449                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1450                 {
1451                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1452                         add_p(plci, LLI, "\x01\x01");
1453                 }
1454                 add_s(plci, CONN_NR, &parms[2]);
1455                 add_s(plci, LLC, &parms[4]);
1456                 add_ai(plci, &parms[5]);
1457                 plci->State = INC_CON_ACCEPT;
1458                 sig_req(plci, CALL_RES, 0);
1459                 return 1;
1460         }
1461         else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1462                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1463                 dump_c_ind_mask(plci);
1464                 Reject = GET_WORD(parms[0].info);
1465                 dbug(1, dprintf("Reject=0x%x", Reject));
1466                 if (Reject)
1467                 {
1468                         if (c_ind_mask_empty(plci))
1469                         {
1470                                 if ((Reject & 0xff00) == 0x3400)
1471                                 {
1472                                         esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1473                                         add_p(plci, ESC, esc_t);
1474                                         add_ai(plci, &parms[5]);
1475                                         sig_req(plci, REJECT, 0);
1476                                 }
1477                                 else if (Reject == 1 || Reject >= 9)
1478                                 {
1479                                         add_ai(plci, &parms[5]);
1480                                         sig_req(plci, HANGUP, 0);
1481                                 }
1482                                 else
1483                                 {
1484                                         esc_t[2] = cau_t[(Reject&0x000f)];
1485                                         add_p(plci, ESC, esc_t);
1486                                         add_ai(plci, &parms[5]);
1487                                         sig_req(plci, REJECT, 0);
1488                                 }
1489                                 plci->appl = appl;
1490                         }
1491                         else
1492                         {
1493                                 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1494                         }
1495                 }
1496                 else {
1497                         plci->appl = appl;
1498                         if (Id & EXT_CONTROLLER) {
1499                                 if (AdvCodecSupport(a, plci, appl, 0)) {
1500                                         dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1501                                         sig_req(plci, HANGUP, 0);
1502                                         return 1;
1503                                 }
1504                                 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1505                                 {
1506                                         Info = add_b23(plci, &parms[1]);
1507                                         if (Info)
1508                                         {
1509                                                 dbug(1, dprintf("connect_res(error from add_b23)"));
1510                                                 sig_req(plci, HANGUP, 0);
1511                                                 return 1;
1512                                         }
1513                                         if (plci->adv_nl)
1514                                         {
1515                                                 nl_req_ncci(plci, ASSIGN, 0);
1516                                         }
1517                                 }
1518                         }
1519                         else
1520                         {
1521                                 plci->tel = 0;
1522                                 if (ch != 2)
1523                                 {
1524                                         Info = add_b23(plci, &parms[1]);
1525                                         if (Info)
1526                                         {
1527                                                 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1528                                                 sig_req(plci, HANGUP, 0);
1529                                                 return 1;
1530                                         }
1531                                 }
1532                                 nl_req_ncci(plci, ASSIGN, 0);
1533                         }
1534
1535                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1536                         {
1537                                 api_save_msg(parms, "wsssss", &plci->saved_msg);
1538                                 plci->spoofed_msg = CALL_RES;
1539                                 plci->internal_command = BLOCK_PLCI;
1540                                 plci->command = 0;
1541                                 dbug(1, dprintf("Spoof"));
1542                         }
1543                         else
1544                         {
1545                                 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1546                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1547                                 {
1548                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1549                                         add_p(plci, LLI, "\x01\x01");
1550                                 }
1551                                 add_s(plci, CONN_NR, &parms[2]);
1552                                 add_s(plci, LLC, &parms[4]);
1553                                 add_ai(plci, &parms[5]);
1554                                 plci->State = INC_CON_ACCEPT;
1555                                 sig_req(plci, CALL_RES, 0);
1556                         }
1557
1558                         for (i = 0; i < max_appl; i++) {
1559                                 if (test_c_ind_mask_bit(plci, i)) {
1560                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1561                                 }
1562                         }
1563                 }
1564         }
1565         return 1;
1566 }
1567
1568 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1569                           PLCI *plci, APPL *appl, API_PARSE *msg)
1570 {
1571         dbug(1, dprintf("connect_a_res"));
1572         return false;
1573 }
1574
1575 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1576                            PLCI *plci, APPL *appl, API_PARSE *msg)
1577 {
1578         word Info;
1579         word i;
1580
1581         dbug(1, dprintf("disconnect_req"));
1582
1583         Info = _WRONG_IDENTIFIER;
1584
1585         if (plci)
1586         {
1587                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1588                 {
1589                         clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1590                         plci->appl = appl;
1591                         for (i = 0; i < max_appl; i++)
1592                         {
1593                                 if (test_c_ind_mask_bit(plci, i))
1594                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595                         }
1596                         plci->State = OUTG_DIS_PENDING;
1597                 }
1598                 if (plci->Sig.Id && plci->appl)
1599                 {
1600                         Info = 0;
1601                         if (plci->Sig.Id != 0xff)
1602                         {
1603                                 if (plci->State != INC_DIS_PENDING)
1604                                 {
1605                                         add_ai(plci, &msg[0]);
1606                                         sig_req(plci, HANGUP, 0);
1607                                         plci->State = OUTG_DIS_PENDING;
1608                                         return 1;
1609                                 }
1610                         }
1611                         else
1612                         {
1613                                 if (plci->NL.Id && !plci->nl_remove_id)
1614                                 {
1615                                         mixer_remove(plci);
1616                                         nl_req_ncci(plci, REMOVE, 0);
1617                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1618                                         sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619                                         plci->State = INC_DIS_PENDING;
1620                                 }
1621                                 return 1;
1622                         }
1623                 }
1624         }
1625
1626         if (!appl)  return false;
1627         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1628         return false;
1629 }
1630
1631 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1632                            PLCI *plci, APPL *appl, API_PARSE *msg)
1633 {
1634         dbug(1, dprintf("disconnect_res"));
1635         if (plci)
1636         {
1637                 /* clear ind mask bit, just in case of collsion of          */
1638                 /* DISCONNECT_IND and CONNECT_RES                           */
1639                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1640                 ncci_free_receive_buffers(plci, 0);
1641                 if (plci_remove_check(plci))
1642                 {
1643                         return 0;
1644                 }
1645                 if (plci->State == INC_DIS_PENDING
1646                     || plci->State == SUSPENDING) {
1647                         if (c_ind_mask_empty(plci)) {
1648                                 if (plci->State != SUSPENDING) plci->State = IDLE;
1649                                 dbug(1, dprintf("chs=%d", plci->channels));
1650                                 if (!plci->channels) {
1651                                         plci_remove(plci);
1652                                 }
1653                         }
1654                 }
1655         }
1656         return 0;
1657 }
1658
1659 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1660                        PLCI *plci, APPL *appl, API_PARSE *parms)
1661 {
1662         word Info;
1663         byte i;
1664
1665         dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1666
1667         Info = _WRONG_IDENTIFIER;
1668         if (a) {
1669                 Info = 0;
1670                 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1671                 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1672                 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1673                 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1674                         a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1675                 }
1676
1677                 /* check if external controller listen and switch listen on or off*/
1678                 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1679                         if (a->profile.Global_Options & ON_BOARD_CODEC) {
1680                                 dummy_plci.State = IDLE;
1681                                 a->codec_listen[appl->Id - 1] = &dummy_plci;
1682                                 a->TelOAD[0] = (byte)(parms[3].length);
1683                                 for (i = 1; parms[3].length >= i && i < 22; i++) {
1684                                         a->TelOAD[i] = parms[3].info[i];
1685                                 }
1686                                 a->TelOAD[i] = 0;
1687                                 a->TelOSA[0] = (byte)(parms[4].length);
1688                                 for (i = 1; parms[4].length >= i && i < 22; i++) {
1689                                         a->TelOSA[i] = parms[4].info[i];
1690                                 }
1691                                 a->TelOSA[i] = 0;
1692                         }
1693                         else Info = 0x2002; /* wrong controller, codec not supported */
1694                 }
1695                 else{               /* clear listen */
1696                         a->codec_listen[appl->Id - 1] = (PLCI *)0;
1697                 }
1698         }
1699         sendf(appl,
1700               _LISTEN_R | CONFIRM,
1701               Id,
1702               Number,
1703               "w", Info);
1704
1705         if (a) listen_check(a);
1706         return false;
1707 }
1708
1709 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1710                      PLCI *plci, APPL *appl, API_PARSE *msg)
1711 {
1712         word i;
1713         API_PARSE *ai;
1714         PLCI *rc_plci = NULL;
1715         API_PARSE ai_parms[5];
1716         word Info = 0;
1717
1718         dbug(1, dprintf("info_req"));
1719         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1720
1721         ai = &msg[1];
1722
1723         if (ai->length)
1724         {
1725                 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1726                 {
1727                         dbug(1, dprintf("AddInfo wrong"));
1728                         Info = _WRONG_MESSAGE_FORMAT;
1729                 }
1730         }
1731         if (!a) Info = _WRONG_STATE;
1732
1733         if (!Info && plci)
1734         {                /* no fac, with CPN, or KEY */
1735                 rc_plci = plci;
1736                 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1737                 {
1738                         /* overlap sending option */
1739                         dbug(1, dprintf("OvlSnd"));
1740                         add_s(plci, CPN, &msg[0]);
1741                         add_s(plci, KEY, &ai_parms[1]);
1742                         sig_req(plci, INFO_REQ, 0);
1743                         send_req(plci);
1744                         return false;
1745                 }
1746
1747                 if (plci->State && ai_parms[2].length)
1748                 {
1749                         /* User_Info option */
1750                         dbug(1, dprintf("UUI"));
1751                         add_s(plci, UUI, &ai_parms[2]);
1752                         sig_req(plci, USER_DATA, 0);
1753                 }
1754                 else if (plci->State && ai_parms[3].length)
1755                 {
1756                         /* Facility option */
1757                         dbug(1, dprintf("FAC"));
1758                         add_s(plci, CPN, &msg[0]);
1759                         add_ai(plci, &msg[1]);
1760                         sig_req(plci, FACILITY_REQ, 0);
1761                 }
1762                 else
1763                 {
1764                         Info = _WRONG_STATE;
1765                 }
1766         }
1767         else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1768         {
1769                 /* NCR_Facility option -> send UUI and Keypad too */
1770                 dbug(1, dprintf("NCR_FAC"));
1771                 if ((i = get_plci(a)))
1772                 {
1773                         rc_plci = &a->plci[i - 1];
1774                         appl->NullCREnable = true;
1775                         rc_plci->internal_command = C_NCR_FAC_REQ;
1776                         rc_plci->appl = appl;
1777                         add_p(rc_plci, CAI, "\x01\x80");
1778                         add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1779                         sig_req(rc_plci, ASSIGN, DSIG_ID);
1780                         send_req(rc_plci);
1781                 }
1782                 else
1783                 {
1784                         Info = _OUT_OF_PLCI;
1785                 }
1786
1787                 if (!Info)
1788                 {
1789                         add_s(rc_plci, CPN, &msg[0]);
1790                         add_ai(rc_plci, &msg[1]);
1791                         sig_req(rc_plci, NCR_FACILITY, 0);
1792                         send_req(rc_plci);
1793                         return false;
1794                         /* for application controlled supplementary services    */
1795                 }
1796         }
1797
1798         if (!rc_plci)
1799         {
1800                 Info = _WRONG_MESSAGE_FORMAT;
1801         }
1802
1803         if (!Info)
1804         {
1805                 send_req(rc_plci);
1806         }
1807         else
1808         {  /* appl is not assigned to a PLCI or error condition */
1809                 dbug(1, dprintf("localInfoCon"));
1810                 sendf(appl,
1811                       _INFO_R | CONFIRM,
1812                       Id,
1813                       Number,
1814                       "w", Info);
1815         }
1816         return false;
1817 }
1818
1819 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1820                      PLCI *plci, APPL *appl, API_PARSE *msg)
1821 {
1822         dbug(1, dprintf("info_res"));
1823         return false;
1824 }
1825
1826 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1827                       PLCI *plci, APPL *appl, API_PARSE *msg)
1828 {
1829         word Info;
1830         byte ret;
1831
1832         dbug(1, dprintf("alert_req"));
1833
1834         Info = _WRONG_IDENTIFIER;
1835         ret = false;
1836         if (plci) {
1837                 Info = _ALERT_IGNORED;
1838                 if (plci->State != INC_CON_ALERT) {
1839                         Info = _WRONG_STATE;
1840                         if (plci->State == INC_CON_PENDING) {
1841                                 Info = 0;
1842                                 plci->State = INC_CON_ALERT;
1843                                 add_ai(plci, &msg[0]);
1844                                 sig_req(plci, CALL_ALERT, 0);
1845                                 ret = 1;
1846                         }
1847                 }
1848         }
1849         sendf(appl,
1850               _ALERT_R | CONFIRM,
1851               Id,
1852               Number,
1853               "w", Info);
1854         return ret;
1855 }
1856
1857 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1858                          PLCI *plci, APPL *appl, API_PARSE *msg)
1859 {
1860         word Info = 0;
1861         word i    = 0;
1862
1863         word selector;
1864         word SSreq;
1865         long relatedPLCIvalue;
1866         DIVA_CAPI_ADAPTER *relatedadapter;
1867         byte *SSparms  = "";
1868         byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1869         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1870         API_PARSE *parms;
1871         API_PARSE ss_parms[11];
1872         PLCI *rplci;
1873         byte cai[15];
1874         dword d;
1875         API_PARSE dummy;
1876
1877         dbug(1, dprintf("facility_req"));
1878         for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1879
1880         parms = &msg[1];
1881
1882         if (!a)
1883         {
1884                 dbug(1, dprintf("wrong Ctrl"));
1885                 Info = _WRONG_IDENTIFIER;
1886         }
1887
1888         selector = GET_WORD(msg[0].info);
1889
1890         if (!Info)
1891         {
1892                 switch (selector)
1893                 {
1894                 case SELECTOR_HANDSET:
1895                         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1896                         break;
1897
1898                 case SELECTOR_SU_SERV:
1899                         if (!msg[1].length)
1900                         {
1901                                 Info = _WRONG_MESSAGE_FORMAT;
1902                                 break;
1903                         }
1904                         SSreq = GET_WORD(&(msg[1].info[1]));
1905                         PUT_WORD(&RCparms[1], SSreq);
1906                         SSparms = RCparms;
1907                         switch (SSreq)
1908                         {
1909                         case S_GET_SUPPORTED_SERVICES:
1910                                 if ((i = get_plci(a)))
1911                                 {
1912                                         rplci = &a->plci[i - 1];
1913                                         rplci->appl = appl;
1914                                         add_p(rplci, CAI, "\x01\x80");
1915                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1916                                         sig_req(rplci, ASSIGN, DSIG_ID);
1917                                         send_req(rplci);
1918                                 }
1919                                 else
1920                                 {
1921                                         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1922                                         SSparms = (byte *)SSstruct;
1923                                         break;
1924                                 }
1925                                 rplci->internal_command = GETSERV_REQ_PEND;
1926                                 rplci->number = Number;
1927                                 rplci->appl = appl;
1928                                 sig_req(rplci, S_SUPPORTED, 0);
1929                                 send_req(rplci);
1930                                 return false;
1931                                 break;
1932
1933                         case S_LISTEN:
1934                                 if (parms->length == 7)
1935                                 {
1936                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1937                                         {
1938                                                 dbug(1, dprintf("format wrong"));
1939                                                 Info = _WRONG_MESSAGE_FORMAT;
1940                                                 break;
1941                                         }
1942                                 }
1943                                 else
1944                                 {
1945                                         Info = _WRONG_MESSAGE_FORMAT;
1946                                         break;
1947                                 }
1948                                 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1949                                 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1950                                 {
1951                                         if ((i = get_plci(a)))
1952                                         {
1953                                                 rplci = &a->plci[i - 1];
1954                                                 rplci->appl = appl;
1955                                                 add_p(rplci, CAI, "\x01\x80");
1956                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1957                                                 sig_req(rplci, ASSIGN, DSIG_ID);
1958                                                 send_req(rplci);
1959                                         }
1960                                         else
1961                                         {
1962                                                 break;
1963                                         }
1964                                         rplci->internal_command = GET_MWI_STATE;
1965                                         rplci->number = Number;
1966                                         sig_req(rplci, MWI_POLL, 0);
1967                                         send_req(rplci);
1968                                 }
1969                                 break;
1970
1971                         case S_HOLD:
1972                                 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1973                                 if (plci && plci->State && plci->SuppState == IDLE)
1974                                 {
1975                                         plci->SuppState = HOLD_REQUEST;
1976                                         plci->command = C_HOLD_REQ;
1977                                         add_s(plci, CAI, &ss_parms[1]);
1978                                         sig_req(plci, CALL_HOLD, 0);
1979                                         send_req(plci);
1980                                         return false;
1981                                 }
1982                                 else Info = 0x3010;                    /* wrong state           */
1983                                 break;
1984                         case S_RETRIEVE:
1985                                 if (plci && plci->State && plci->SuppState == CALL_HELD)
1986                                 {
1987                                         if (Id & EXT_CONTROLLER)
1988                                         {
1989                                                 if (AdvCodecSupport(a, plci, appl, 0))
1990                                                 {
1991                                                         Info = 0x3010;                    /* wrong state           */
1992                                                         break;
1993                                                 }
1994                                         }
1995                                         else plci->tel = 0;
1996
1997                                         plci->SuppState = RETRIEVE_REQUEST;
1998                                         plci->command = C_RETRIEVE_REQ;
1999                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
2000                                         {
2001                                                 plci->spoofed_msg = CALL_RETRIEVE;
2002                                                 plci->internal_command = BLOCK_PLCI;
2003                                                 plci->command = 0;
2004                                                 dbug(1, dprintf("Spoof"));
2005                                                 return false;
2006                                         }
2007                                         else
2008                                         {
2009                                                 sig_req(plci, CALL_RETRIEVE, 0);
2010                                                 send_req(plci);
2011                                                 return false;
2012                                         }
2013                                 }
2014                                 else Info = 0x3010;                    /* wrong state           */
2015                                 break;
2016                         case S_SUSPEND:
2017                                 if (parms->length)
2018                                 {
2019                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2020                                         {
2021                                                 dbug(1, dprintf("format wrong"));
2022                                                 Info = _WRONG_MESSAGE_FORMAT;
2023                                                 break;
2024                                         }
2025                                 }
2026                                 if (plci && plci->State)
2027                                 {
2028                                         add_s(plci, CAI, &ss_parms[2]);
2029                                         plci->command = SUSPEND_REQ;
2030                                         sig_req(plci, SUSPEND, 0);
2031                                         plci->State = SUSPENDING;
2032                                         send_req(plci);
2033                                 }
2034                                 else Info = 0x3010;                    /* wrong state           */
2035                                 break;
2036
2037                         case S_RESUME:
2038                                 if (!(i = get_plci(a)))
2039                                 {
2040                                         Info = _OUT_OF_PLCI;
2041                                         break;
2042                                 }
2043                                 rplci = &a->plci[i - 1];
2044                                 rplci->appl = appl;
2045                                 rplci->number = Number;
2046                                 rplci->tel = 0;
2047                                 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2048                                 /* check 'external controller' bit for codec support */
2049                                 if (Id & EXT_CONTROLLER)
2050                                 {
2051                                         if (AdvCodecSupport(a, rplci, appl, 0))
2052                                         {
2053                                                 rplci->Id = 0;
2054                                                 Info = 0x300A;
2055                                                 break;
2056                                         }
2057                                 }
2058                                 if (parms->length)
2059                                 {
2060                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2061                                         {
2062                                                 dbug(1, dprintf("format wrong"));
2063                                                 rplci->Id = 0;
2064                                                 Info = _WRONG_MESSAGE_FORMAT;
2065                                                 break;
2066                                         }
2067                                 }
2068                                 dummy.length = 0;
2069                                 dummy.info = "\x00";
2070                                 add_b1(rplci, &dummy, 0, 0);
2071                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
2072                                 {
2073                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
2074                                         add_p(rplci, LLI, "\x01\x01");
2075                                 }
2076                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2077                                 sig_req(rplci, ASSIGN, DSIG_ID);
2078                                 send_req(rplci);
2079                                 add_s(rplci, CAI, &ss_parms[2]);
2080                                 rplci->command = RESUME_REQ;
2081                                 sig_req(rplci, RESUME, 0);
2082                                 rplci->State = RESUMING;
2083                                 send_req(rplci);
2084                                 break;
2085
2086                         case S_CONF_BEGIN: /* Request */
2087                         case S_CONF_DROP:
2088                         case S_CONF_ISOLATE:
2089                         case S_CONF_REATTACH:
2090                                 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2091                                 {
2092                                         dbug(1, dprintf("format wrong"));
2093                                         Info = _WRONG_MESSAGE_FORMAT;
2094                                         break;
2095                                 }
2096                                 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2097                                 {
2098                                         d = GET_DWORD(ss_parms[2].info);
2099                                         if (d >= 0x80)
2100                                         {
2101                                                 dbug(1, dprintf("format wrong"));
2102                                                 Info = _WRONG_MESSAGE_FORMAT;
2103                                                 break;
2104                                         }
2105                                         plci->ptyState = (byte)SSreq;
2106                                         plci->command = 0;
2107                                         cai[0] = 2;
2108                                         switch (SSreq)
2109                                         {
2110                                         case S_CONF_BEGIN:
2111                                                 cai[1] = CONF_BEGIN;
2112                                                 plci->internal_command = CONF_BEGIN_REQ_PEND;
2113                                                 break;
2114                                         case S_CONF_DROP:
2115                                                 cai[1] = CONF_DROP;
2116                                                 plci->internal_command = CONF_DROP_REQ_PEND;
2117                                                 break;
2118                                         case S_CONF_ISOLATE:
2119                                                 cai[1] = CONF_ISOLATE;
2120                                                 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2121                                                 break;
2122                                         case S_CONF_REATTACH:
2123                                                 cai[1] = CONF_REATTACH;
2124                                                 plci->internal_command = CONF_REATTACH_REQ_PEND;
2125                                                 break;
2126                                         }
2127                                         cai[2] = (byte)d; /* Conference Size resp. PartyId */
2128                                         add_p(plci, CAI, cai);
2129                                         sig_req(plci, S_SERVICE, 0);
2130                                         send_req(plci);
2131                                         return false;
2132                                 }
2133                                 else Info = 0x3010;                    /* wrong state           */
2134                                 break;
2135
2136                         case S_ECT:
2137                         case S_3PTY_BEGIN:
2138                         case S_3PTY_END:
2139                         case S_CONF_ADD:
2140                                 if (parms->length == 7)
2141                                 {
2142                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2143                                         {
2144                                                 dbug(1, dprintf("format wrong"));
2145                                                 Info = _WRONG_MESSAGE_FORMAT;
2146                                                 break;
2147                                         }
2148                                 }
2149                                 else if (parms->length == 8) /* workaround for the T-View-S */
2150                                 {
2151                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2152                                         {
2153                                                 dbug(1, dprintf("format wrong"));
2154                                                 Info = _WRONG_MESSAGE_FORMAT;
2155                                                 break;
2156                                         }
2157                                 }
2158                                 else
2159                                 {
2160                                         Info = _WRONG_MESSAGE_FORMAT;
2161                                         break;
2162                                 }
2163                                 if (!msg[1].length)
2164                                 {
2165                                         Info = _WRONG_MESSAGE_FORMAT;
2166                                         break;
2167                                 }
2168                                 if (!plci)
2169                                 {
2170                                         Info = _WRONG_IDENTIFIER;
2171                                         break;
2172                                 }
2173                                 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2174                                 relatedPLCIvalue &= 0x0000FFFF;
2175                                 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2176                                 /* controller starts with 0 up to (max_adapter - 1) */
2177                                 if (((relatedPLCIvalue & 0x7f) == 0)
2178                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2179                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2180                                 {
2181                                         if (SSreq == S_3PTY_END)
2182                                         {
2183                                                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2184                                                 rplci = plci;
2185                                         }
2186                                         else
2187                                         {
2188                                                 Info = 0x3010;                    /* wrong state           */
2189                                                 break;
2190                                         }
2191                                 }
2192                                 else
2193                                 {
2194                                         relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2195                                         relatedPLCIvalue >>= 8;
2196                                         /* find PLCI PTR*/
2197                                         for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2198                                         {
2199                                                 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2200                                                 {
2201                                                         rplci = &relatedadapter->plci[i];
2202                                                 }
2203                                         }
2204                                         if (!rplci || !relatedPLCIvalue)
2205                                         {
2206                                                 if (SSreq == S_3PTY_END)
2207                                                 {
2208                                                         dbug(1, dprintf("use 2nd PLCI=PLCI"));
2209                                                         rplci = plci;
2210                                                 }
2211                                                 else
2212                                                 {
2213                                                         Info = 0x3010;                    /* wrong state           */
2214                                                         break;
2215                                                 }
2216                                         }
2217                                 }
2218 /*
2219   dbug(1, dprintf("rplci:%x", rplci));
2220   dbug(1, dprintf("plci:%x", plci));
2221   dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2222   dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2223   dbug(1, dprintf("SSreq:%x", SSreq));
2224   dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2225   dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2226   dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2227 */
2228                                 /* send PTY/ECT req, cannot check all states because of US stuff */
2229                                 if (!rplci->internal_command && rplci->appl)
2230                                 {
2231                                         plci->command = 0;
2232                                         rplci->relatedPTYPLCI = plci;
2233                                         plci->relatedPTYPLCI = rplci;
2234                                         rplci->ptyState = (byte)SSreq;
2235                                         if (SSreq == S_ECT)
2236                                         {
2237                                                 rplci->internal_command = ECT_REQ_PEND;
2238                                                 cai[1] = ECT_EXECUTE;
2239
2240                                                 rplci->vswitchstate = 0;
2241                                                 rplci->vsprot = 0;
2242                                                 rplci->vsprotdialect = 0;
2243                                                 plci->vswitchstate = 0;
2244                                                 plci->vsprot = 0;
2245                                                 plci->vsprotdialect = 0;
2246
2247                                         }
2248                                         else if (SSreq == S_CONF_ADD)
2249                                         {
2250                                                 rplci->internal_command = CONF_ADD_REQ_PEND;
2251                                                 cai[1] = CONF_ADD;
2252                                         }
2253                                         else
2254                                         {
2255                                                 rplci->internal_command = PTY_REQ_PEND;
2256                                                 cai[1] = (byte)(SSreq - 3);
2257                                         }
2258                                         rplci->number = Number;
2259                                         if (plci != rplci) /* explicit invocation */
2260                                         {
2261                                                 cai[0] = 2;
2262                                                 cai[2] = plci->Sig.Id;
2263                                                 dbug(1, dprintf("explicit invocation"));
2264                                         }
2265                                         else
2266                                         {
2267                                                 dbug(1, dprintf("implicit invocation"));
2268                                                 cai[0] = 1;
2269                                         }
2270                                         add_p(rplci, CAI, cai);
2271                                         sig_req(rplci, S_SERVICE, 0);
2272                                         send_req(rplci);
2273                                         return false;
2274                                 }
2275                                 else
2276                                 {
2277                                         dbug(0, dprintf("Wrong line"));
2278                                         Info = 0x3010;                    /* wrong state           */
2279                                         break;
2280                                 }
2281                                 break;
2282
2283                         case S_CALL_DEFLECTION:
2284                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2285                                 {
2286                                         dbug(1, dprintf("format wrong"));
2287                                         Info = _WRONG_MESSAGE_FORMAT;
2288                                         break;
2289                                 }
2290                                 if (!plci)
2291                                 {
2292                                         Info = _WRONG_IDENTIFIER;
2293                                         break;
2294                                 }
2295                                 /* reuse unused screening indicator */
2296                                 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2297                                 plci->command = 0;
2298                                 plci->internal_command = CD_REQ_PEND;
2299                                 appl->CDEnable = true;
2300                                 cai[0] = 1;
2301                                 cai[1] = CALL_DEFLECTION;
2302                                 add_p(plci, CAI, cai);
2303                                 add_p(plci, CPN, ss_parms[3].info);
2304                                 sig_req(plci, S_SERVICE, 0);
2305                                 send_req(plci);
2306                                 return false;
2307                                 break;
2308
2309                         case S_CALL_FORWARDING_START:
2310                                 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2311                                 {
2312                                         dbug(1, dprintf("format wrong"));
2313                                         Info = _WRONG_MESSAGE_FORMAT;
2314                                         break;
2315                                 }
2316
2317                                 if ((i = get_plci(a)))
2318                                 {
2319                                         rplci = &a->plci[i - 1];
2320                                         rplci->appl = appl;
2321                                         add_p(rplci, CAI, "\x01\x80");
2322                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2323                                         sig_req(rplci, ASSIGN, DSIG_ID);
2324                                         send_req(rplci);
2325                                 }
2326                                 else
2327                                 {
2328                                         Info = _OUT_OF_PLCI;
2329                                         break;
2330                                 }
2331
2332                                 /* reuse unused screening indicator */
2333                                 rplci->internal_command = CF_START_PEND;
2334                                 rplci->appl = appl;
2335                                 rplci->number = Number;
2336                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2337                                 cai[0] = 2;
2338                                 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2339                                 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2340                                 add_p(rplci, CAI, cai);
2341                                 add_p(rplci, OAD, ss_parms[5].info);
2342                                 add_p(rplci, CPN, ss_parms[6].info);
2343                                 sig_req(rplci, S_SERVICE, 0);
2344                                 send_req(rplci);
2345                                 return false;
2346                                 break;
2347
2348                         case S_INTERROGATE_DIVERSION:
2349                         case S_INTERROGATE_NUMBERS:
2350                         case S_CALL_FORWARDING_STOP:
2351                         case S_CCBS_REQUEST:
2352                         case S_CCBS_DEACTIVATE:
2353                         case S_CCBS_INTERROGATE:
2354                                 switch (SSreq)
2355                                 {
2356                                 case S_INTERROGATE_NUMBERS:
2357                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2358                                         {
2359                                                 dbug(0, dprintf("format wrong"));
2360                                                 Info = _WRONG_MESSAGE_FORMAT;
2361                                         }
2362                                         break;
2363                                 case S_CCBS_REQUEST:
2364                                 case S_CCBS_DEACTIVATE:
2365                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2366                                         {
2367                                                 dbug(0, dprintf("format wrong"));
2368                                                 Info = _WRONG_MESSAGE_FORMAT;
2369                                         }
2370                                         break;
2371                                 case S_CCBS_INTERROGATE:
2372                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2373                                         {
2374                                                 dbug(0, dprintf("format wrong"));
2375                                                 Info = _WRONG_MESSAGE_FORMAT;
2376                                         }
2377                                         break;
2378                                 default:
2379                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2380                                         {
2381                                                 dbug(0, dprintf("format wrong"));
2382                                                 Info = _WRONG_MESSAGE_FORMAT;
2383                                                 break;
2384                                         }
2385                                         break;
2386                                 }
2387
2388                                 if (Info) break;
2389                                 if ((i = get_plci(a)))
2390                                 {
2391                                         rplci = &a->plci[i - 1];
2392                                         switch (SSreq)
2393                                         {
2394                                         case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2395                                                 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2396                                                 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2397                                                 break;
2398                                         case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2399                                                 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2400                                                 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2401                                                 break;
2402                                         case S_CALL_FORWARDING_STOP:
2403                                                 rplci->internal_command = CF_STOP_PEND;
2404                                                 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2405                                                 break;
2406                                         case S_CCBS_REQUEST:
2407                                                 cai[1] = CCBS_REQUEST;
2408                                                 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2409                                                 break;
2410                                         case S_CCBS_DEACTIVATE:
2411                                                 cai[1] = CCBS_DEACTIVATE;
2412                                                 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2413                                                 break;
2414                                         case S_CCBS_INTERROGATE:
2415                                                 cai[1] = CCBS_INTERROGATE;
2416                                                 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2417                                                 break;
2418                                         default:
2419                                                 cai[1] = 0;
2420                                                 break;
2421                                         }
2422                                         rplci->appl = appl;
2423                                         rplci->number = Number;
2424                                         add_p(rplci, CAI, "\x01\x80");
2425                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2426                                         sig_req(rplci, ASSIGN, DSIG_ID);
2427                                         send_req(rplci);
2428                                 }
2429                                 else
2430                                 {
2431                                         Info = _OUT_OF_PLCI;
2432                                         break;
2433                                 }
2434
2435                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2436                                 switch (SSreq)
2437                                 {
2438                                 case S_INTERROGATE_NUMBERS:
2439                                         cai[0] = 1;
2440                                         add_p(rplci, CAI, cai);
2441                                         break;
2442                                 case S_CCBS_REQUEST:
2443                                 case S_CCBS_DEACTIVATE:
2444                                         cai[0] = 3;
2445                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2446                                         add_p(rplci, CAI, cai);
2447                                         break;
2448                                 case S_CCBS_INTERROGATE:
2449                                         cai[0] = 3;
2450                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2451                                         add_p(rplci, CAI, cai);
2452                                         add_p(rplci, OAD, ss_parms[4].info);
2453                                         break;
2454                                 default:
2455                                         cai[0] = 2;
2456                                         cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2457                                         add_p(rplci, CAI, cai);
2458                                         add_p(rplci, OAD, ss_parms[5].info);
2459                                         break;
2460                                 }
2461
2462                                 sig_req(rplci, S_SERVICE, 0);
2463                                 send_req(rplci);
2464                                 return false;
2465                                 break;
2466
2467                         case S_MWI_ACTIVATE:
2468                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2469                                 {
2470                                         dbug(1, dprintf("format wrong"));
2471                                         Info = _WRONG_MESSAGE_FORMAT;
2472                                         break;
2473                                 }
2474                                 if (!plci)
2475                                 {
2476                                         if ((i = get_plci(a)))
2477                                         {
2478                                                 rplci = &a->plci[i - 1];
2479                                                 rplci->appl = appl;
2480                                                 rplci->cr_enquiry = true;
2481                                                 add_p(rplci, CAI, "\x01\x80");
2482                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2483                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2484                                                 send_req(rplci);
2485                                         }
2486                                         else
2487                                         {
2488                                                 Info = _OUT_OF_PLCI;
2489                                                 break;
2490                                         }
2491                                 }
2492                                 else
2493                                 {
2494                                         rplci = plci;
2495                                         rplci->cr_enquiry = false;
2496                                 }
2497
2498                                 rplci->command = 0;
2499                                 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2500                                 rplci->appl = appl;
2501                                 rplci->number = Number;
2502
2503                                 cai[0] = 13;
2504                                 cai[1] = ACTIVATION_MWI; /* Function */
2505                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2506                                 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2507                                 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2508                                 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2509                                 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2510                                 add_p(rplci, CAI, cai);
2511                                 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2512                                 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2513                                 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2514                                 add_p(rplci, UID, ss_parms[10].info); /* Time */
2515                                 sig_req(rplci, S_SERVICE, 0);
2516                                 send_req(rplci);
2517                                 return false;
2518
2519                         case S_MWI_DEACTIVATE:
2520                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2521                                 {
2522                                         dbug(1, dprintf("format wrong"));
2523                                         Info = _WRONG_MESSAGE_FORMAT;
2524                                         break;
2525                                 }
2526                                 if (!plci)
2527                                 {
2528                                         if ((i = get_plci(a)))
2529                                         {
2530                                                 rplci = &a->plci[i - 1];
2531                                                 rplci->appl = appl;
2532                                                 rplci->cr_enquiry = true;
2533                                                 add_p(rplci, CAI, "\x01\x80");
2534                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2535                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2536                                                 send_req(rplci);
2537                                         }
2538                                         else
2539                                         {
2540                                                 Info = _OUT_OF_PLCI;
2541                                                 break;
2542                                         }
2543                                 }
2544                                 else
2545                                 {
2546                                         rplci = plci;
2547                                         rplci->cr_enquiry = false;
2548                                 }
2549
2550                                 rplci->command = 0;
2551                                 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2552                                 rplci->appl = appl;
2553                                 rplci->number = Number;
2554
2555                                 cai[0] = 5;
2556                                 cai[1] = DEACTIVATION_MWI; /* Function */
2557                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2558                                 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2559                                 add_p(rplci, CAI, cai);
2560                                 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2561                                 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2562                                 sig_req(rplci, S_SERVICE, 0);
2563                                 send_req(rplci);
2564                                 return false;
2565
2566                         default:
2567                                 Info = 0x300E;  /* not supported */
2568                                 break;
2569                         }
2570                         break; /* case SELECTOR_SU_SERV: end */
2571
2572
2573                 case SELECTOR_DTMF:
2574                         return (dtmf_request(Id, Number, a, plci, appl, msg));
2575
2576
2577
2578                 case SELECTOR_LINE_INTERCONNECT:
2579                         return (mixer_request(Id, Number, a, plci, appl, msg));
2580
2581
2582
2583                 case PRIV_SELECTOR_ECHO_CANCELLER:
2584                         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2585                         return (ec_request(Id, Number, a, plci, appl, msg));
2586
2587                 case SELECTOR_ECHO_CANCELLER:
2588                         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2589                         return (ec_request(Id, Number, a, plci, appl, msg));
2590
2591
2592                 case SELECTOR_V42BIS:
2593                 default:
2594                         Info = _FACILITY_NOT_SUPPORTED;
2595                         break;
2596                 } /* end of switch (selector) */
2597         }
2598
2599         dbug(1, dprintf("SendFacRc"));
2600         sendf(appl,
2601               _FACILITY_R | CONFIRM,
2602               Id,
2603               Number,
2604               "wws", Info, selector, SSparms);
2605         return false;
2606 }
2607
2608 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2609                          PLCI *plci, APPL *appl, API_PARSE *msg)
2610 {
2611         dbug(1, dprintf("facility_res"));
2612         return false;
2613 }
2614
2615 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2616                            PLCI *plci, APPL *appl, API_PARSE *parms)
2617 {
2618         word Info = 0;
2619         byte req;
2620         byte len;
2621         word w;
2622         word fax_control_bits, fax_feature_bits, fax_info_change;
2623         API_PARSE *ncpi;
2624         byte pvc[2];
2625
2626         API_PARSE fax_parms[9];
2627         word i;
2628
2629
2630         dbug(1, dprintf("connect_b3_req"));
2631         if (plci)
2632         {
2633                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2634                     || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2635                 {
2636                         Info = _WRONG_STATE;
2637                 }
2638                 else
2639                 {
2640                         /* local reply if assign unsuccessful
2641                            or B3 protocol allows only one layer 3 connection
2642                            and already connected
2643                            or B2 protocol not any LAPD
2644                            and connect_b3_req contradicts originate/answer direction */
2645                         if (!plci->NL.Id
2646                             || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2647                                 && ((plci->channels != 0)
2648                                     || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2649                                         && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2650                         {
2651                                 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2652                                                 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2653                                 Info = _WRONG_STATE;
2654                                 sendf(appl,
2655                                       _CONNECT_B3_R | CONFIRM,
2656                                       Id,
2657                                       Number,
2658                                       "w", Info);
2659                                 return false;
2660                         }
2661                         plci->requested_options_conn = 0;
2662
2663                         req = N_CONNECT;
2664                         ncpi = &parms[0];
2665                         if (plci->B3_prot == 2 || plci->B3_prot == 3)
2666                         {
2667                                 if (ncpi->length > 2)
2668                                 {
2669                                         /* check for PVC */
2670                                         if (ncpi->info[2] || ncpi->info[3])
2671                                         {
2672                                                 pvc[0] = ncpi->info[3];
2673                                                 pvc[1] = ncpi->info[2];
2674                                                 add_d(plci, 2, pvc);
2675                                                 req = N_RESET;
2676                                         }
2677                                         else
2678                                         {
2679                                                 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2680                                                 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2681                                         }
2682                                 }
2683                         }
2684                         else if (plci->B3_prot == 5)
2685                         {
2686                                 if (plci->NL.Id && !plci->nl_remove_id)
2687                                 {
2688                                         fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2689                                         fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2690                                         if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2691                                             || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2692                                         {
2693                                                 len = offsetof(T30_INFO, universal_6);
2694                                                 fax_info_change = false;
2695                                                 if (ncpi->length >= 4)
2696                                                 {
2697                                                         w = GET_WORD(&ncpi->info[3]);
2698                                                         if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2699                                                         {
2700                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2701                                                                         (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2702                                                                                ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2703                                                                 fax_info_change = true;
2704                                                         }
2705                                                         fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2706                                                         if (w & 0x0002)  /* Fax-polling request */
2707                                                                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2708                                                         if ((w & 0x0004) /* Request to send / poll another document */
2709                                                             && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2710                                                         {
2711                                                                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2712                                                         }
2713                                                         if (ncpi->length >= 6)
2714                                                         {
2715                                                                 w = GET_WORD(&ncpi->info[5]);
2716                                                                 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2717                                                                 {
2718                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2719                                                                         fax_info_change = true;
2720                                                                 }
2721
2722                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2723                                                                     && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2724                                                                 {
2725                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2726                                                                 }
2727                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2728                                                                     && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2729                                                                 {
2730                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2731                                                                 }
2732                                                                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2733                                                                                       T30_CONTROL_BIT_ACCEPT_PASSWORD);
2734                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2735                                                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2736                                                                 {
2737                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2738                                                                                 Info = _WRONG_MESSAGE_FORMAT;
2739                                                                         else
2740                                                                         {
2741                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2742                                                                                     & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2743                                                                                 {
2744                                                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2745                                                                                         if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2746                                                                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2747                                                                                 }
2748                                                                                 w = fax_parms[4].length;
2749                                                                                 if (w > 20)
2750                                                                                         w = 20;
2751                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2752                                                                                 for (i = 0; i < w; i++)
2753                                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2754                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2755                                                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2756                                                                                 w = fax_parms[5].length;
2757                                                                                 if (w > 20)
2758                                                                                         w = 20;
2759                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2760                                                                                 for (i = 0; i < w; i++)
2761                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2762                                                                                 w = fax_parms[6].length;
2763                                                                                 if (w > 20)
2764                                                                                         w = 20;
2765                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2766                                                                                 for (i = 0; i < w; i++)
2767                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2768                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2769                                                                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2770                                                                                 {
2771                                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2772                                                                                         {
2773                                                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2774                                                                                                 plci->fax_connect_info_buffer[len++] = 0;
2775                                                                                         }
2776                                                                                         else
2777                                                                                         {
2778                                                                                                 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2779                                                                                                         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2780                                                                                                 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2781                                                                                                 for (i = 0; i < fax_parms[7].length; i++)
2782                                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2783                                                                                         }
2784                                                                                 }
2785                                                                         }
2786                                                                 }
2787                                                                 else
2788                                                                 {
2789                                                                         len = offsetof(T30_INFO, universal_6);
2790                                                                 }
2791                                                                 fax_info_change = true;
2792
2793                                                         }
2794                                                         if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2795                                                         {
2796                                                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2797                                                                 fax_info_change = true;
2798                                                         }
2799                                                 }
2800                                                 if (Info == GOOD)
2801                                                 {
2802                                                         plci->fax_connect_info_length = len;
2803                                                         if (fax_info_change)
2804                                                         {
2805                                                                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2806                                                                 {
2807                                                                         start_internal_command(Id, plci, fax_connect_info_command);
2808                                                                         return false;
2809                                                                 }
2810                                                                 else
2811                                                                 {
2812                                                                         start_internal_command(Id, plci, fax_adjust_b23_command);
2813                                                                         return false;
2814                                                                 }
2815                                                         }
2816                                                 }
2817                                         }
2818                                         else  Info = _WRONG_STATE;
2819                                 }
2820                                 else  Info = _WRONG_STATE;
2821                         }
2822
2823                         else if (plci->B3_prot == B3_RTP)
2824                         {
2825                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2826                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2827                                 for (w = 0; w < ncpi->length; w++)
2828                                         plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2829                                 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2830                                 return false;
2831                         }
2832
2833                         if (!Info)
2834                         {
2835                                 nl_req_ncci(plci, req, 0);
2836                                 return 1;
2837                         }
2838                 }
2839         }
2840         else Info = _WRONG_IDENTIFIER;
2841
2842         sendf(appl,
2843               _CONNECT_B3_R | CONFIRM,
2844               Id,
2845               Number,
2846               "w", Info);
2847         return false;
2848 }
2849
2850 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2851                            PLCI *plci, APPL *appl, API_PARSE *parms)
2852 {
2853         word ncci;
2854         API_PARSE *ncpi;
2855         byte req;
2856
2857         word w;
2858
2859
2860         API_PARSE fax_parms[9];
2861         word i;
2862         byte len;
2863
2864
2865         dbug(1, dprintf("connect_b3_res"));
2866
2867         ncci = (word)(Id >> 16);
2868         if (plci && ncci) {
2869                 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2870                         if (GET_WORD(&parms[0].info[0]) != 0)
2871                         {
2872                                 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2873                                 channel_request_xon(plci, a->ncci_ch[ncci]);
2874                                 channel_xmit_xon(plci);
2875                                 cleanup_ncci_data(plci, ncci);
2876                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
2877                                 return 1;
2878                         }
2879                         a->ncci_state[ncci] = INC_ACT_PENDING;
2880
2881                         req = N_CONNECT_ACK;
2882                         ncpi = &parms[1];
2883                         if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884                         {
2885
2886                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2887                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2888                                 {
2889                                         if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2890                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2891                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2892                                         {
2893                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2894                                                 if (plci->fax_connect_info_length < len)
2895                                                 {
2896                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2897                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2898                                                 }
2899                                                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2900                                                 {
2901                                                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2902                                                 }
2903                                                 else
2904                                                 {
2905                                                         if (plci->fax_connect_info_length <= len)
2906                                                                 plci->fax_connect_info_buffer[len] = 0;
2907                                                         len += 1 + plci->fax_connect_info_buffer[len];
2908                                                         if (plci->fax_connect_info_length <= len)
2909                                                                 plci->fax_connect_info_buffer[len] = 0;
2910                                                         len += 1 + plci->fax_connect_info_buffer[len];
2911                                                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2912                                                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2913                                                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2914                                                         for (i = 0; i < fax_parms[7].length; i++)
2915                                                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2916                                                 }
2917                                                 plci->fax_connect_info_length = len;
2918                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2919                                                 start_internal_command(Id, plci, fax_connect_ack_command);
2920                                                 return false;
2921                                         }
2922                                 }
2923
2924                                 nl_req_ncci(plci, req, (byte)ncci);
2925                                 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2926                                     && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2927                                 {
2928                                         if (plci->B3_prot == 4)
2929                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2930                                         else
2931                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2932                                         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2933                                 }
2934                         }
2935
2936                         else if (plci->B3_prot == B3_RTP)
2937                         {
2938                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2939                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2940                                 for (w = 0; w < ncpi->length; w++)
2941                                         plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2942                                 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2943                                 return false;
2944                         }
2945
2946                         else
2947                         {
2948                                 if (ncpi->length > 2) {
2949                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2950                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2951                                 }
2952                                 nl_req_ncci(plci, req, (byte)ncci);
2953                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2954                                 if (plci->adjust_b_restore)
2955                                 {
2956                                         plci->adjust_b_restore = false;
2957                                         start_internal_command(Id, plci, adjust_b_restore);
2958                                 }
2959                         }
2960                         return 1;
2961                 }
2962         }
2963         return false;
2964 }
2965
2966 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2967                              PLCI *plci, APPL *appl, API_PARSE *parms)
2968 {
2969         word ncci;
2970
2971         ncci = (word)(Id >> 16);
2972         dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2973
2974         if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2975             && (plci->State != OUTG_DIS_PENDING))
2976         {
2977                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2978                         a->ncci_state[ncci] = CONNECTED;
2979                         if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2980                         channel_request_xon(plci, a->ncci_ch[ncci]);
2981                         channel_xmit_xon(plci);
2982                 }
2983         }
2984         return false;
2985 }
2986
2987 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2988                               PLCI *plci, APPL *appl, API_PARSE *parms)
2989 {
2990         word Info;
2991         word ncci;
2992         API_PARSE *ncpi;
2993
2994         dbug(1, dprintf("disconnect_b3_req"));
2995
2996         Info = _WRONG_IDENTIFIER;
2997         ncci = (word)(Id >> 16);
2998         if (plci && ncci)
2999         {
3000                 Info = _WRONG_STATE;
3001                 if ((a->ncci_state[ncci] == CONNECTED)
3002                     || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3003                     || (a->ncci_state[ncci] == INC_CON_PENDING)
3004                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3005                 {
3006                         a->ncci_state[ncci] = OUTG_DIS_PENDING;
3007                         channel_request_xon(plci, a->ncci_ch[ncci]);
3008                         channel_xmit_xon(plci);
3009
3010                         if (a->ncci[ncci].data_pending
3011                             && ((plci->B3_prot == B3_TRANSPARENT)
3012                                 || (plci->B3_prot == B3_T30)
3013                                 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3014                         {
3015                                 plci->send_disc = (byte)ncci;
3016                                 plci->command = 0;
3017                                 return false;
3018                         }
3019                         else
3020                         {
3021                                 cleanup_ncci_data(plci, ncci);
3022
3023                                 if (plci->B3_prot == 2 || plci->B3_prot == 3)
3024                                 {
3025                                         ncpi = &parms[0];
3026                                         if (ncpi->length > 3)
3027                                         {
3028                                                 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3029                                         }
3030                                 }
3031                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
3032                         }
3033                         return 1;
3034                 }
3035         }
3036         sendf(appl,
3037               _DISCONNECT_B3_R | CONFIRM,
3038               Id,
3039               Number,
3040               "w", Info);
3041         return false;
3042 }
3043
3044 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3045                               PLCI *plci, APPL *appl, API_PARSE *parms)
3046 {
3047         word ncci;
3048         word i;
3049
3050         ncci = (word)(Id >> 16);
3051         dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3052         if (plci && ncci) {
3053                 plci->requested_options_conn = 0;
3054                 plci->fax_connect_info_length = 0;
3055                 plci->ncpi_state = 0x00;
3056                 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3057                     && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3058                 {
3059                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3060                 }
3061                 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3062                 if (i < MAX_CHANNELS_PER_PLCI) {
3063                         if (plci->channels)plci->channels--;
3064                         for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3065                         plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3066
3067                         ncci_free_receive_buffers(plci, ncci);
3068
3069                         if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3070                                 if (plci->State == SUSPENDING) {
3071                                         sendf(plci->appl,
3072                                               _FACILITY_I,
3073                                               Id & 0xffffL,
3074                                               0,
3075                                               "ws", (word)3, "\x03\x04\x00\x00");
3076                                         sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3077                                 }
3078                                 plci_remove(plci);
3079                                 plci->State = IDLE;
3080                         }
3081                 }
3082                 else
3083                 {
3084                         if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3085                             && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3086                             && (a->ncci_state[ncci] == INC_DIS_PENDING))
3087                         {
3088                                 ncci_free_receive_buffers(plci, ncci);
3089
3090                                 nl_req_ncci(plci, N_EDATA, (byte)ncci);
3091
3092                                 plci->adapter->ncci_state[ncci] = IDLE;
3093                                 start_internal_command(Id, plci, fax_disconnect_command);
3094                                 return 1;
3095                         }
3096                 }
3097         }
3098         return false;
3099 }
3100
3101 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3102                         PLCI *plci, APPL *appl, API_PARSE *parms)
3103 {
3104         NCCI *ncci_ptr;
3105         DATA_B3_DESC *data;
3106         word Info;
3107         word ncci;
3108         word i;
3109
3110         dbug(1, dprintf("data_b3_req"));
3111
3112         Info = _WRONG_IDENTIFIER;
3113         ncci = (word)(Id >> 16);
3114         dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3115
3116         if (plci && ncci)
3117         {
3118                 Info = _WRONG_STATE;
3119                 if ((a->ncci_state[ncci] == CONNECTED)
3120                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3121                 {
3122                         /* queue data */
3123                         ncci_ptr = &(a->ncci[ncci]);
3124                         i = ncci_ptr->data_out + ncci_ptr->data_pending;
3125                         if (i >= MAX_DATA_B3)
3126                                 i -= MAX_DATA_B3;
3127                         data = &(ncci_ptr->DBuffer[i]);
3128                         data->Number = Number;
3129                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3130                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3131                         {
3132
3133                                 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3134
3135                         }
3136                         else
3137                                 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3138                         data->Length = GET_WORD(parms[1].info);
3139                         data->Handle = GET_WORD(parms[2].info);
3140                         data->Flags = GET_WORD(parms[3].info);
3141                         (ncci_ptr->data_pending)++;
3142
3143                         /* check for delivery confirmation */
3144                         if (data->Flags & 0x0004)
3145                         {
3146                                 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3147                                 if (i >= MAX_DATA_ACK)
3148                                         i -= MAX_DATA_ACK;
3149                                 ncci_ptr->DataAck[i].Number = data->Number;
3150                                 ncci_ptr->DataAck[i].Handle = data->Handle;
3151                                 (ncci_ptr->data_ack_pending)++;
3152                         }
3153
3154                         send_data(plci);
3155                         return false;
3156                 }
3157         }
3158         if (appl)
3159         {
3160                 if (plci)
3161                 {
3162                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3163                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3164                         {
3165
3166                                 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3167
3168                         }
3169                 }
3170                 sendf(appl,
3171                       _DATA_B3_R | CONFIRM,
3172                       Id,
3173                       Number,
3174                       "ww", GET_WORD(parms[2].info), Info);
3175         }
3176         return false;
3177 }
3178
3179 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3180                         PLCI *plci, APPL *appl, API_PARSE *parms)
3181 {
3182         word n;
3183         word ncci;
3184         word NCCIcode;
3185
3186         dbug(1, dprintf("data_b3_res"));
3187
3188         ncci = (word)(Id >> 16);
3189         if (plci && ncci) {
3190                 n = GET_WORD(parms[0].info);
3191                 dbug(1, dprintf("free(%d)", n));
3192                 NCCIcode = ncci | (((word) a->Id) << 8);
3193                 if (n < appl->MaxBuffer &&
3194                     appl->DataNCCI[n] == NCCIcode &&
3195                     (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3196                         dbug(1, dprintf("found"));
3197                         appl->DataNCCI[n] = 0;
3198
3199                         if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3200                                 channel_request_xon(plci, a->ncci_ch[ncci]);
3201                         }
3202                         channel_xmit_xon(plci);
3203
3204                         if (appl->DataFlags[n] & 4) {
3205                                 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3206                                 return 1;
3207                         }
3208                 }
3209         }
3210         return false;
3211 }
3212
3213 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3214                          PLCI *plci, APPL *appl, API_PARSE *parms)
3215 {
3216         word Info;
3217         word ncci;
3218
3219         dbug(1, dprintf("reset_b3_req"));
3220
3221         Info = _WRONG_IDENTIFIER;
3222         ncci = (word)(Id >> 16);
3223         if (plci && ncci)
3224         {
3225                 Info = _WRONG_STATE;
3226                 switch (plci->B3_prot)
3227                 {
3228                 case B3_ISO8208:
3229                 case B3_X25_DCE:
3230                         if (a->ncci_state[ncci] == CONNECTED)
3231                         {
3232                                 nl_req_ncci(plci, N_RESET, (byte)ncci);
3233                                 send_req(plci);
3234                                 Info = GOOD;
3235                         }
3236                         break;
3237                 case B3_TRANSPARENT:
3238                         if (a->ncci_state[ncci] == CONNECTED)
3239                         {
3240                                 start_internal_command(Id, plci, reset_b3_command);
3241                                 Info = GOOD;
3242                         }
3243                         break;
3244                 }
3245         }
3246         /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3247         sendf(appl,
3248               _RESET_B3_R | CONFIRM,
3249               Id,
3250               Number,
3251               "w", Info);
3252         return false;
3253 }
3254
3255 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3256                          PLCI *plci, APPL *appl, API_PARSE *parms)
3257 {
3258         word ncci;
3259
3260         dbug(1, dprintf("reset_b3_res"));
3261
3262         ncci = (word)(Id >> 16);
3263         if (plci && ncci) {
3264                 switch (plci->B3_prot)
3265                 {
3266                 case B3_ISO8208:
3267                 case B3_X25_DCE:
3268                         if (a->ncci_state[ncci] == INC_RES_PENDING)
3269                         {
3270                                 a->ncci_state[ncci] = CONNECTED;
3271                                 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3272                                 return true;
3273                         }
3274                         break;
3275                 }
3276         }
3277         return false;
3278 }
3279
3280 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3281                                  PLCI *plci, APPL *appl, API_PARSE *parms)
3282 {
3283         word ncci;
3284         API_PARSE *ncpi;
3285         byte req;
3286
3287         dbug(1, dprintf("connect_b3_t90_a_res"));
3288
3289         ncci = (word)(Id >> 16);
3290         if (plci && ncci) {
3291                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3292                         a->ncci_state[ncci] = CONNECTED;
3293                 }
3294                 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3295                         a->ncci_state[ncci] = CONNECTED;
3296
3297                         req = N_CONNECT_ACK;
3298
3299                         /* parms[0]==0 for CAPI original message definition! */
3300                         if (parms[0].info) {
3301                                 ncpi = &parms[1];
3302                                 if (ncpi->length > 2) {
3303                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3304                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3305                                 }
3306                         }
3307                         nl_req_ncci(plci, req, (byte)ncci);
3308                         return 1;
3309                 }
3310         }
3311         return false;
3312 }
3313
3314
3315 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3316                          PLCI *plci, APPL *appl, API_PARSE *msg)
3317 {
3318         word Info = 0;
3319         word i;
3320         byte tel;
3321         API_PARSE bp_parms[7];
3322
3323         if (!plci || !msg)
3324         {
3325                 Info = _WRONG_IDENTIFIER;
3326         }
3327         else
3328         {
3329                 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3330                                 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3331                 dbug(1, dprintf("PlciState=0x%x", plci->State));
3332                 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3333
3334                 /* check if no channel is open, no B3 connected only */
3335                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3336                     || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3337                 {
3338                         Info = _WRONG_STATE;
3339                 }
3340                 /* check message format and fill bp_parms pointer */
3341                 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3342                 {
3343                         Info = _WRONG_MESSAGE_FORMAT;
3344                 }
3345                 else
3346                 {
3347                         if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3348                         {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3349                                 if (Id & EXT_CONTROLLER)
3350                                 {
3351                                         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3352                                         return 0;
3353                                 }
3354                                 plci->State = INC_CON_CONNECTED_ALERT;
3355                                 plci->appl = appl;
3356                                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3357                                 dump_c_ind_mask(plci);
3358                                 for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3359                                 {                         /* its quasi a connect        */
3360                                         if (test_c_ind_mask_bit(plci, i))
3361                                                 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3362                                 }
3363                         }
3364
3365                         api_save_msg(msg, "s", &plci->saved_msg);
3366                         tel = plci->tel;
3367                         if (Id & EXT_CONTROLLER)
3368                         {
3369                                 if (tel) /* external controller in use by this PLCI */
3370                                 {
3371                                         if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3372                                         {
3373                                                 dbug(1, dprintf("Ext_Ctrl in use 1"));
3374                                                 Info = _WRONG_STATE;
3375                                         }
3376                                 }
3377                                 else  /* external controller NOT in use by this PLCI ? */
3378                                 {
3379                                         if (a->AdvSignalPLCI)
3380                                         {
3381                                                 dbug(1, dprintf("Ext_Ctrl in use 2"));
3382                                                 Info = _WRONG_STATE;
3383                                         }
3384                                         else /* activate the codec */
3385                                         {
3386                                                 dbug(1, dprintf("Ext_Ctrl start"));
3387                                                 if (AdvCodecSupport(a, plci, appl, 0))
3388                                                 {
3389                                                         dbug(1, dprintf("Error in codec procedures"));
3390                                                         Info = _WRONG_STATE;
3391                                                 }
3392                                                 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3393                                                 {
3394                                                         plci->spoofed_msg = AWAITING_SELECT_B;
3395                                                         plci->internal_command = BLOCK_PLCI; /* lock other commands */
3396                                                         plci->command = 0;
3397                                                         dbug(1, dprintf("continue if codec loaded"));
3398                                                         return false;
3399                                                 }
3400                                         }
3401                                 }
3402                         }
3403                         else /* external controller bit is OFF */
3404                         {
3405                                 if (tel) /* external controller in use, need to switch off */
3406                                 {
3407                                         if (a->AdvSignalAppl == appl)
3408                                         {
3409                                                 CodecIdCheck(a, plci);
3410                                                 plci->tel = 0;
3411                                                 plci->adv_nl = 0;
3412                                                 dbug(1, dprintf("Ext_Ctrl disable"));
3413                                         }
3414                                         else
3415                                         {
3416                                                 dbug(1, dprintf("Ext_Ctrl not requested"));
3417                                         }
3418                                 }
3419                         }
3420                         if (!Info)
3421                         {
3422                                 if (plci->call_dir & CALL_DIR_OUT)
3423                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3424                                 else if (plci->call_dir & CALL_DIR_IN)
3425                                         plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3426                                 start_internal_command(Id, plci, select_b_command);
3427                                 return false;
3428                         }
3429                 }
3430         }
3431         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3432         return false;
3433 }
3434
3435 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3436                              PLCI *plci, APPL *appl, API_PARSE *parms)
3437 {
3438         word command;
3439         word i;
3440         word ncci;
3441         API_PARSE *m;
3442         API_PARSE m_parms[5];
3443         word codec;
3444         byte req;
3445         byte ch;
3446         byte dir;
3447         static byte chi[2] = {0x01, 0x00};
3448         static byte lli[2] = {0x01, 0x00};
3449         static byte codec_cai[2] = {0x01, 0x01};
3450         static byte null_msg = {0};
3451         static API_PARSE null_parms = { 0, &null_msg };
3452         PLCI *v_plci;
3453         word Info = 0;
3454
3455         dbug(1, dprintf("manufacturer_req"));
3456         for (i = 0; i < 5; i++) m_parms[i].length = 0;
3457
3458         if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3459                 Info = _WRONG_MESSAGE_FORMAT;
3460         }
3461         command = GET_WORD(parms[1].info);
3462         m = &parms[2];
3463         if (!Info)
3464         {
3465                 switch (command) {
3466                 case _DI_ASSIGN_PLCI:
3467                         if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3468                                 Info = _WRONG_MESSAGE_FORMAT;
3469                                 break;
3470                         }
3471                         codec = GET_WORD(m_parms[0].info);
3472                         ch = m_parms[1].info[0];
3473                         dir = m_parms[2].info[0];
3474                         if ((i = get_plci(a))) {
3475                                 plci = &a->plci[i - 1];
3476                                 plci->appl = appl;
3477                                 plci->command = _MANUFACTURER_R;
3478                                 plci->m_command = command;
3479                                 plci->number = Number;
3480                                 plci->State = LOCAL_CONNECT;
3481                                 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3482                                 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3483
3484                                 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3485                                         chi[1] = (byte)(0x80 | ch);
3486                                         lli[1] = 0;
3487                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3488                                         switch (codec)
3489                                         {
3490                                         case 0:
3491                                                 Info = add_b1(plci, &m_parms[3], 0, 0);
3492                                                 break;
3493                                         case 1:
3494                                                 add_p(plci, CAI, codec_cai);
3495                                                 break;
3496                                                 /* manual 'swich on' to the codec support without signalling */
3497                                                 /* first 'assign plci' with this function, then use */
3498                                         case 2:
3499                                                 if (AdvCodecSupport(a, plci, appl, 0)) {
3500                                                         Info = _RESOURCE_ERROR;
3501                                                 }
3502                                                 else {
3503                                                         Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3504                                                         lli[1] = 0x10; /* local call codec stream */
3505                                                 }
3506                                                 break;
3507                                         }
3508
3509                                         plci->State = LOCAL_CONNECT;
3510                                         plci->manufacturer = true;
3511                                         plci->command = _MANUFACTURER_R;
3512                                         plci->m_command = command;
3513                                         plci->number = Number;
3514
3515                                         if (!Info)
3516                                         {
3517                                                 add_p(plci, LLI, lli);
3518                                                 add_p(plci, CHI, chi);
3519                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3520                                                 sig_req(plci, ASSIGN, DSIG_ID);
3521
3522                                                 if (!codec)
3523                                                 {
3524                                                         Info = add_b23(plci, &m_parms[3]);
3525                                                         if (!Info)
3526                                                         {
3527                                                                 nl_req_ncci(plci, ASSIGN, 0);
3528                                                                 send_req(plci);
3529                                                         }
3530                                                 }
3531                                                 if (!Info)
3532                                                 {
3533                                                         dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3534                                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
3535                                                         {
3536                                                                 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3537                                                                 plci->spoofed_msg = AWAITING_MANUF_CON;
3538                                                                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3539                                                                 plci->command = 0;
3540                                                                 send_req(plci);
3541                                                                 return false;
3542                                                         }
3543                                                         if (dir == 1) {
3544                                                                 sig_req(plci, CALL_REQ, 0);
3545                                                         }
3546                                                         else if (!dir) {
3547                                                                 sig_req(plci, LISTEN_REQ, 0);
3548                                                         }
3549                                                         send_req(plci);
3550                                                 }
3551                                                 else
3552                                                 {
3553                                                         sendf(appl,
3554                                                               _MANUFACTURER_R | CONFIRM,
3555                                                               Id,
3556                                                               Number,
3557                                                               "dww", _DI_MANU_ID, command, Info);
3558                                                         return 2;
3559                                                 }
3560                                         }
3561                                 }
3562                         }
3563                         else  Info = _OUT_OF_PLCI;
3564                         break;
3565
3566                 case _DI_IDI_CTRL:
3567                         if (!plci)
3568                         {
3569                                 Info = _WRONG_IDENTIFIER;
3570                                 break;
3571                         }
3572                         if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3573                                 Info = _WRONG_MESSAGE_FORMAT;
3574                                 break;
3575                         }
3576                         req = m_parms[0].info[0];
3577                         plci->command = _MANUFACTURER_R;
3578                         plci->m_command = command;
3579                         plci->number = Number;
3580                         if (req == CALL_REQ)
3581                         {
3582                                 plci->b_channel = getChannel(&m_parms[1]);
3583                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3584                                 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3585                                 {
3586                                         plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3587                                         plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3588                                         plci->command = 0;
3589                                         break;
3590                                 }
3591                         }
3592                         else if (req == LAW_REQ)
3593                         {
3594                                 plci->cr_enquiry = true;
3595                         }
3596                         add_ss(plci, FTY, &m_parms[1]);
3597                         sig_req(plci, req, 0);
3598                         send_req(plci);
3599                         if (req == HANGUP)
3600                         {
3601                                 if (plci->NL.Id && !plci->nl_remove_id)
3602                                 {
3603                                         if (plci->channels)
3604                                         {
3605                                                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3606                                                 {
3607                                                         if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3608                                                         {
3609                                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3610                                                                 cleanup_ncci_data(plci, ncci);
3611                                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
3612                                                         }
3613                                                 }
3614                                         }
3615                                         mixer_remove(plci);
3616                                         nl_req_ncci(plci, REMOVE, 0);
3617                                         send_req(plci);
3618                                 }
3619                         }
3620                         break;
3621
3622                 case _DI_SIG_CTRL:
3623                         /* signalling control for loop activation B-channel */
3624                         if (!plci)
3625                         {
3626                                 Info = _WRONG_IDENTIFIER;
3627                                 break;
3628                         }
3629                         if (m->length) {
3630                                 plci->command = _MANUFACTURER_R;
3631                                 plci->number = Number;
3632                                 add_ss(plci, FTY, m);
3633                                 sig_req(plci, SIG_CTRL, 0);
3634                                 send_req(plci);
3635                         }
3636                         else Info = _WRONG_MESSAGE_FORMAT;
3637                         break;
3638
3639                 case _DI_RXT_CTRL:
3640                         /* activation control for receiver/transmitter B-channel */
3641                         if (!plci)
3642                         {
3643                                 Info = _WRONG_IDENTIFIER;
3644                                 break;
3645                         }
3646                         if (m->length) {
3647                                 plci->command = _MANUFACTURER_R;
3648                                 plci->number = Number;
3649                                 add_ss(plci, FTY, m);
3650                                 sig_req(plci, DSP_CTRL, 0);
3651                                 send_req(plci);
3652                         }
3653                         else Info = _WRONG_MESSAGE_FORMAT;
3654                         break;
3655
3656                 case _DI_ADV_CODEC:
3657                 case _DI_DSP_CTRL:
3658                         /* TEL_CTRL commands to support non standard adjustments: */
3659                         /* Ring on/off, Handset micro volume, external micro vol. */
3660                         /* handset+external speaker volume, receiver+transm. gain,*/
3661                         /* handsfree on (hookinfo off), set mixer command         */
3662
3663                         if (command == _DI_ADV_CODEC)
3664                         {
3665                                 if (!a->AdvCodecPLCI) {
3666                                         Info = _WRONG_STATE;
3667                                         break;
3668                                 }
3669                                 v_plci = a->AdvCodecPLCI;
3670                         }
3671                         else
3672                         {
3673                                 if (plci
3674                                     && (m->length >= 3)
3675                                     && (m->info[1] == 0x1c)
3676                                     && (m->info[2] >= 1))
3677                                 {
3678                                         if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3679                                         {
3680                                                 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3681                                                 {
3682                                                         Info = _WRONG_STATE;
3683                                                         break;
3684                                                 }
3685                                                 a->adv_voice_coef_length = m->info[2] - 1;
3686                                                 if (a->adv_voice_coef_length > m->length - 3)
3687                                                         a->adv_voice_coef_length = (byte)(m->length - 3);
3688                                                 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3689                                                         a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3690                                                 for (i = 0; i < a->adv_voice_coef_length; i++)
3691                                                         a->adv_voice_coef_buffer[i] = m->info[4 + i];
3692                                                 if (plci->B1_facilities & B1_FACILITY_VOICE)
3693                                                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3694                                                 break;
3695                                         }
3696                                         else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3697                                         {
3698                                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3699                                                 {
3700                                                         Info = _FACILITY_NOT_SUPPORTED;
3701                                                         break;
3702                                                 }
3703
3704                                                 plci->dtmf_parameter_length = m->info[2] - 1;
3705                                                 if (plci->dtmf_parameter_length > m->length - 3)
3706                                                         plci->dtmf_parameter_length = (byte)(m->length - 3);
3707                                                 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3708                                                         plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3709                                                 for (i = 0; i < plci->dtmf_parameter_length; i++)
3710                                                         plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3711                                                 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3712                                                         dtmf_parameter_write(plci);
3713                                                 break;
3714
3715                                         }
3716                                 }
3717                                 v_plci = plci;
3718                         }
3719
3720                         if (!v_plci)
3721                         {
3722                                 Info = _WRONG_IDENTIFIER;
3723                                 break;
3724                         }
3725                         if (m->length) {
3726                                 add_ss(v_plci, FTY, m);
3727                                 sig_req(v_plci, TEL_CTRL, 0);
3728                                 send_req(v_plci);
3729                         }
3730                         else Info = _WRONG_MESSAGE_FORMAT;
3731
3732                         break;
3733
3734                 case _DI_OPTIONS_REQUEST:
3735                         if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3736                                 Info = _WRONG_MESSAGE_FORMAT;
3737                                 break;
3738                         }
3739                         if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3740                         {
3741                                 Info = _FACILITY_NOT_SUPPORTED;
3742                                 break;
3743                         }
3744                         a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3745                         break;
3746
3747
3748
3749                 default:
3750                         Info = _WRONG_MESSAGE_FORMAT;
3751                         break;
3752                 }
3753         }
3754
3755         sendf(appl,
3756               _MANUFACTURER_R | CONFIRM,
3757               Id,
3758               Number,
3759               "dww", _DI_MANU_ID, command, Info);
3760         return false;
3761 }
3762
3763
3764 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3765                              PLCI *plci, APPL *appl, API_PARSE *msg)
3766 {
3767         word indication;
3768
3769         API_PARSE m_parms[3];
3770         API_PARSE *ncpi;
3771         API_PARSE fax_parms[9];
3772         word i;
3773         byte len;
3774
3775
3776         dbug(1, dprintf("manufacturer_res"));
3777
3778         if ((msg[0].length == 0)
3779             || (msg[1].length == 0)
3780             || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3781         {
3782                 return false;
3783         }
3784         indication = GET_WORD(msg[1].info);
3785         switch (indication)
3786         {
3787
3788         case _DI_NEGOTIATE_B3:
3789                 if (!plci)
3790                         break;
3791                 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3792                     || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3793                 {
3794                         dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3795                         break;
3796                 }
3797                 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3798                 {
3799                         dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3800                         break;
3801                 }
3802                 ncpi = &m_parms[1];
3803                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3804                 if (plci->fax_connect_info_length < len)
3805                 {
3806                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3807                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3808                 }
3809                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3810                 {
3811                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3812                 }
3813                 else
3814                 {
3815                         if (plci->fax_connect_info_length <= len)
3816                                 plci->fax_connect_info_buffer[len] = 0;
3817                         len += 1 + plci->fax_connect_info_buffer[len];
3818                         if (plci->fax_connect_info_length <= len)
3819                                 plci->fax_connect_info_buffer[len] = 0;
3820                         len += 1 + plci->fax_connect_info_buffer[len];
3821                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3822                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3823                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3824                         for (i = 0; i < fax_parms[7].length; i++)
3825                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3826                 }
3827                 plci->fax_connect_info_length = len;
3828                 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3829                 start_internal_command(Id, plci, fax_edata_ack_command);
3830                 break;
3831
3832         }
3833         return false;
3834 }
3835
3836 /*------------------------------------------------------------------*/
3837 /* IDI callback function                                            */
3838 /*------------------------------------------------------------------*/
3839
3840 void callback(ENTITY *e)
3841 {
3842         DIVA_CAPI_ADAPTER *a;
3843         APPL *appl;
3844         PLCI *plci;
3845         CAPI_MSG *m;
3846         word i, j;
3847         byte rc;
3848         byte ch;
3849         byte req;
3850         byte global_req;
3851         int no_cancel_rc;
3852
3853         dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3854                         (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3855
3856         a = &(adapter[(byte)e->user[0]]);
3857         plci = &(a->plci[e->user[1]]);
3858         no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3859
3860         /*
3861           If new protocol code and new XDI is used then CAPI should work
3862           fully in accordance with IDI cpec an look on callback field instead
3863           of Rc field for return codes.
3864         */
3865         if (((e->complete == 0xff) && no_cancel_rc) ||
3866             (e->Rc && !no_cancel_rc)) {
3867                 rc = e->Rc;
3868                 ch = e->RcCh;
3869                 req = e->Req;
3870                 e->Rc = 0;
3871
3872                 if (e->user[0] & 0x8000)
3873                 {
3874                         /*
3875                           If REMOVE request was sent then we have to wait until
3876                           return code with Id set to zero arrives.
3877                           All other return codes should be ignored.
3878                         */
3879                         if (req == REMOVE)
3880                         {
3881                                 if (e->Id)
3882                                 {
3883                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3884                                         return;
3885                                 }
3886                                 channel_flow_control_remove(plci);
3887                                 for (i = 0; i < 256; i++)
3888                                 {
3889                                         if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3890                                                 a->FlowControlIdTable[i] = 0;
3891                                 }
3892                                 plci->nl_remove_id = 0;
3893                                 if (plci->rx_dma_descriptor > 0) {
3894                                         diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3895                                         plci->rx_dma_descriptor = 0;
3896                                 }
3897                         }
3898                         if (rc == OK_FC)
3899                         {
3900                                 a->FlowControlIdTable[ch] = e->Id;
3901                                 a->FlowControlSkipTable[ch] = 0;
3902
3903                                 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3904                                 a->ch_flow_plci[ch] = plci->Id;
3905                                 plci->nl_req = 0;
3906                         }
3907                         else
3908                         {
3909                                 /*
3910                                   Cancel return codes self, if feature was requested
3911                                 */
3912                                 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3913                                         a->FlowControlIdTable[ch] = 0;
3914                                         if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3915                                                 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3916                                                 return;
3917                                         }
3918                                 }
3919
3920                                 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3921                                 {
3922                                         a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3923                                         if (ch == e->ReqCh)
3924                                                 plci->nl_req = 0;
3925                                 }
3926                                 else
3927                                         plci->nl_req = 0;
3928                         }
3929                         if (plci->nl_req)
3930                                 control_rc(plci, 0, rc, ch, 0, true);
3931                         else
3932                         {
3933                                 if (req == N_XON)
3934                                 {
3935                                         channel_x_on(plci, ch);
3936                                         if (plci->internal_command)
3937                                                 control_rc(plci, req, rc, ch, 0, true);
3938                                 }
3939                                 else
3940                                 {
3941                                         if (plci->nl_global_req)
3942                                         {
3943                                                 global_req = plci->nl_global_req;
3944                                                 plci->nl_global_req = 0;
3945                                                 if (rc != ASSIGN_OK) {
3946                                                         e->Id = 0;
3947                                                         if (plci->rx_dma_descriptor > 0) {
3948                                                                 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3949                                                                 plci->rx_dma_descriptor = 0;
3950                                                         }
3951                                                 }
3952                                                 channel_xmit_xon(plci);
3953                                                 control_rc(plci, 0, rc, ch, global_req, true);
3954                                         }
3955                                         else if (plci->data_sent)
3956                                         {
3957                                                 channel_xmit_xon(plci);
3958                                                 plci->data_sent = false;
3959                                                 plci->NL.XNum = 1;
3960                                                 data_rc(plci, ch);
3961                                                 if (plci->internal_command)
3962                                                         control_rc(plci, req, rc, ch, 0, true);
3963                                         }
3964                                         else
3965                                         {
3966                                                 channel_xmit_xon(plci);
3967                                                 control_rc(plci, req, rc, ch, 0, true);
3968                                         }
3969                                 }
3970                         }
3971                 }
3972                 else
3973                 {
3974                         /*
3975                           If REMOVE request was sent then we have to wait until
3976                           return code with Id set to zero arrives.
3977                           All other return codes should be ignored.
3978                         */
3979                         if (req == REMOVE)
3980                         {
3981                                 if (e->Id)
3982                                 {
3983                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3984                                         return;
3985                                 }
3986                                 plci->sig_remove_id = 0;
3987                         }
3988                         plci->sig_req = 0;
3989                         if (plci->sig_global_req)
3990                         {
3991                                 global_req = plci->sig_global_req;
3992                                 plci->sig_global_req = 0;
3993                                 if (rc != ASSIGN_OK)
3994                                         e->Id = 0;
3995                                 channel_xmit_xon(plci);
3996                                 control_rc(plci, 0, rc, ch, global_req, false);
3997                         }
3998                         else
3999                         {
4000                                 channel_xmit_xon(plci);
4001                                 control_rc(plci, req, rc, ch, 0, false);
4002                         }
4003                 }
4004                 /*
4005                   Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4006                   same callback. Also if new XDI and protocol code used then jump
4007                   direct to finish.
4008                 */
4009                 if (no_cancel_rc) {
4010                         channel_xmit_xon(plci);
4011                         goto capi_callback_suffix;
4012                 }
4013         }
4014
4015         channel_xmit_xon(plci);
4016
4017         if (e->Ind) {
4018                 if (e->user[0] & 0x8000) {
4019                         byte Ind = e->Ind & 0x0f;
4020                         byte Ch = e->IndCh;
4021                         if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4022                             (a->ch_flow_plci[Ch] == plci->Id)) {
4023                                 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4024                                         dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4025                                 }
4026                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4027                         }
4028                         nl_ind(plci);
4029                         if ((e->RNR != 1) &&
4030                             (a->ch_flow_plci[Ch] == plci->Id) &&
4031                             (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4032                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4033                                 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4034                         }
4035                 } else {
4036                         sig_ind(plci);
4037                 }
4038                 e->Ind = 0;
4039         }
4040
4041 capi_callback_suffix:
4042
4043         while (!plci->req_in
4044                && !plci->internal_command
4045                && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4046         {
4047                 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4048
4049                 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4050
4051                 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4052                 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4053                 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4054                                 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4055                 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4056                 {
4057                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4058                         plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4059                 }
4060                 else
4061                 {
4062                         plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4063                 }
4064                 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4065                 {
4066                         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4067                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4068                 }
4069                 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4070                 {
4071                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4072                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4073                 }
4074                 i = api_put(appl, m);
4075                 if (i != 0)
4076                 {
4077                         if (m->header.command == _DATA_B3_R)
4078
4079                                 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4080
4081                         dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4082                         break;
4083                 }
4084
4085                 if (plci->li_notify_update)
4086                 {
4087                         plci->li_notify_update = false;
4088                         mixer_notify_update(plci, false);
4089                 }
4090
4091         }
4092         send_data(plci);
4093         send_req(plci);
4094 }
4095
4096
4097 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4098                        byte nl_rc)
4099 {
4100         dword Id;
4101         dword rId;
4102         word Number;
4103         word Info = 0;
4104         word i;
4105         word ncci;
4106         DIVA_CAPI_ADAPTER *a;
4107         APPL *appl;
4108         PLCI *rplci;
4109         byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4110         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4111
4112         if (!plci) {
4113                 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4114                 return;
4115         }
4116         dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4117         if (plci->req_in != plci->req_out)
4118         {
4119                 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4120                 {
4121                         dbug(1, dprintf("req_1return"));
4122                         return;
4123                 }
4124                 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4125         }
4126         plci->req_in = plci->req_in_start = plci->req_out = 0;
4127         dbug(1, dprintf("control_rc"));
4128
4129         appl = plci->appl;
4130         a = plci->adapter;
4131         ncci = a->ch_ncci[ch];
4132         if (appl)
4133         {
4134                 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4135                 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4136                 Number = plci->number;
4137                 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));
4138                 dbug(1, dprintf("channels=0x%x", plci->channels));
4139                 if (plci_remove_check(plci))
4140                         return;
4141                 if (req == REMOVE && rc == ASSIGN_OK)
4142                 {
4143                         sig_req(plci, HANGUP, 0);
4144                         sig_req(plci, REMOVE, 0);
4145                         send_req(plci);
4146                 }
4147                 if (plci->command)
4148                 {
4149                         switch (plci->command)
4150                         {
4151                         case C_HOLD_REQ:
4152                                 dbug(1, dprintf("HoldRC=0x%x", rc));
4153                                 SSparms[1] = (byte)S_HOLD;
4154                                 if (rc != OK)
4155                                 {
4156                                         plci->SuppState = IDLE;
4157                                         Info = 0x2001;
4158                                 }
4159                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4160                                 break;
4161
4162                         case C_RETRIEVE_REQ:
4163                                 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4164                                 SSparms[1] = (byte)S_RETRIEVE;
4165                                 if (rc != OK)
4166                                 {
4167                                         plci->SuppState = CALL_HELD;
4168                                         Info = 0x2001;
4169                                 }
4170                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4171                                 break;
4172
4173                         case _INFO_R:
4174                                 dbug(1, dprintf("InfoRC=0x%x", rc));
4175                                 if (rc != OK) Info = _WRONG_STATE;
4176                                 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4177                                 break;
4178
4179                         case _CONNECT_R:
4180                                 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4181                                 if (plci->State == INC_DIS_PENDING)
4182                                         break;
4183                                 if (plci->Sig.Id != 0xff)
4184                                 {
4185                                         if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4186                                             || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4187                                         {
4188                                                 dbug(1, dprintf("No more IDs/Call_Req failed"));
4189                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4190                                                 plci_remove(plci);
4191                                                 plci->State = IDLE;
4192                                                 break;
4193                                         }
4194                                         if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4195                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4196                                 }
4197                                 else /* D-ch activation */
4198                                 {
4199                                         if (rc != ASSIGN_OK)
4200                                         {
4201                                                 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4202                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4203                                                 plci_remove(plci);
4204                                                 plci->State = IDLE;
4205                                                 break;
4206                                         }
4207                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4208                                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4209                                         plci->State = INC_ACT_PENDING;
4210                                 }
4211                                 break;
4212
4213                         case _CONNECT_I | RESPONSE:
4214                                 if (plci->State != INC_DIS_PENDING)
4215                                         plci->State = INC_CON_ACCEPT;
4216                                 break;
4217
4218                         case _DISCONNECT_R:
4219                                 if (plci->State == INC_DIS_PENDING)
4220                                         break;
4221                                 if (plci->Sig.Id != 0xff)
4222                                 {
4223                                         plci->State = OUTG_DIS_PENDING;
4224                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4225                                 }
4226                                 break;
4227
4228                         case SUSPEND_REQ:
4229                                 break;
4230
4231                         case RESUME_REQ:
4232                                 break;
4233
4234                         case _CONNECT_B3_R:
4235                                 if (rc != OK)
4236                                 {
4237                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4238                                         break;
4239                                 }
4240                                 ncci = get_ncci(plci, ch, 0);
4241                                 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4242                                 plci->channels++;
4243                                 if (req == N_RESET)
4244                                 {
4245                                         a->ncci_state[ncci] = INC_ACT_PENDING;
4246                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4247                                         sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4248                                 }
4249                                 else
4250                                 {
4251                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4252                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4253                                 }
4254                                 break;
4255
4256                         case _CONNECT_B3_I | RESPONSE:
4257                                 break;
4258
4259                         case _RESET_B3_R:
4260 /*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4261                                 break;
4262
4263                         case _DISCONNECT_B3_R:
4264                                 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4265                                 break;
4266
4267                         case _MANUFACTURER_R:
4268                                 break;
4269
4270                         case PERM_LIST_REQ:
4271                                 if (rc != OK)
4272                                 {
4273                                         Info = _WRONG_IDENTIFIER;
4274                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4275                                         plci_remove(plci);
4276                                 }
4277                                 else
4278                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4279                                 break;
4280
4281                         default:
4282                                 break;
4283                         }
4284                         plci->command = 0;
4285                 }
4286                 else if (plci->internal_command)
4287                 {
4288                         switch (plci->internal_command)
4289                         {
4290                         case BLOCK_PLCI:
4291                                 return;
4292
4293                         case GET_MWI_STATE:
4294                                 if (rc == OK) /* command supported, wait for indication */
4295                                 {
4296                                         return;
4297                                 }
4298                                 plci_remove(plci);
4299                                 break;
4300
4301                                 /* Get Supported Services */
4302                         case GETSERV_REQ_PEND:
4303                                 if (rc == OK) /* command supported, wait for indication */
4304                                 {
4305                                         break;
4306                                 }
4307                                 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4308                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4309                                 plci_remove(plci);
4310                                 break;
4311
4312                         case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4313                         case INTERR_NUMBERS_REQ_PEND:
4314                         case CF_START_PEND:                  /* Call Forwarding Start pending */
4315                         case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4316                         case CCBS_REQUEST_REQ_PEND:
4317                         case CCBS_DEACTIVATE_REQ_PEND:
4318                         case CCBS_INTERROGATE_REQ_PEND:
4319                                 switch (plci->internal_command)
4320                                 {
4321                                 case INTERR_DIVERSION_REQ_PEND:
4322                                         SSparms[1] = S_INTERROGATE_DIVERSION;
4323                                         break;
4324                                 case INTERR_NUMBERS_REQ_PEND:
4325                                         SSparms[1] = S_INTERROGATE_NUMBERS;
4326                                         break;
4327                                 case CF_START_PEND:
4328                                         SSparms[1] = S_CALL_FORWARDING_START;
4329                                         break;
4330                                 case CF_STOP_PEND:
4331                                         SSparms[1] = S_CALL_FORWARDING_STOP;
4332                                         break;
4333                                 case CCBS_REQUEST_REQ_PEND:
4334                                         SSparms[1] = S_CCBS_REQUEST;
4335                                         break;
4336                                 case CCBS_DEACTIVATE_REQ_PEND:
4337                                         SSparms[1] = S_CCBS_DEACTIVATE;
4338                                         break;
4339                                 case CCBS_INTERROGATE_REQ_PEND:
4340                                         SSparms[1] = S_CCBS_INTERROGATE;
4341                                         break;
4342                                 }
4343                                 if (global_req == ASSIGN)
4344                                 {
4345                                         dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4346                                         return;
4347                                 }
4348                                 if (!plci->appl) break;
4349                                 if (rc == ISDN_GUARD_REJ)
4350                                 {
4351                                         Info = _CAPI_GUARD_ERROR;
4352                                 }
4353                                 else if (rc != OK)
4354                                 {
4355                                         Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4356                                 }
4357                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4358                                       plci->number, "wws", Info, (word)3, SSparms);
4359                                 if (Info) plci_remove(plci);
4360                                 break;
4361
4362                                 /* 3pty conference pending */
4363                         case PTY_REQ_PEND:
4364                                 if (!plci->relatedPTYPLCI) break;
4365                                 rplci = plci->relatedPTYPLCI;
4366                                 SSparms[1] = plci->ptyState;
4367                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4368                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4369                                 if (rc != OK)
4370                                 {
4371                                         Info = 0x300E; /* not supported */
4372                                         plci->relatedPTYPLCI = NULL;
4373                                         plci->ptyState = 0;
4374                                 }
4375                                 sendf(rplci->appl,
4376                                       _FACILITY_R | CONFIRM,
4377                                       rId,
4378                                       plci->number,
4379                                       "wws", Info, (word)3, SSparms);
4380                                 break;
4381
4382                                 /* Explicit Call Transfer pending */
4383                         case ECT_REQ_PEND:
4384                                 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4385                                 if (!plci->relatedPTYPLCI) break;
4386                                 rplci = plci->relatedPTYPLCI;
4387                                 SSparms[1] = S_ECT;
4388                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4389                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4390                                 if (rc != OK)
4391                                 {
4392                                         Info = 0x300E; /* not supported */
4393                                         plci->relatedPTYPLCI = NULL;
4394                                         plci->ptyState = 0;
4395                                 }
4396                                 sendf(rplci->appl,
4397                                       _FACILITY_R | CONFIRM,
4398                                       rId,
4399                                       plci->number,
4400                                       "wws", Info, (word)3, SSparms);
4401                                 break;
4402
4403                         case _MANUFACTURER_R:
4404                                 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4405                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4406                                 {
4407                                         dbug(1, dprintf("No more IDs"));
4408                                         sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4409                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4410                                 }
4411                                 break;
4412
4413                         case _CONNECT_R:
4414                                 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4415                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4416                                 {
4417                                         dbug(1, dprintf("No more IDs"));
4418                                         sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4419                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4420                                 }
4421                                 break;
4422
4423                         case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4424                                 return;
4425
4426                         case PERM_COD_CALL:
4427                                 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4428                                 plci->internal_command = PERM_COD_CONN_PEND;
4429                                 return;
4430
4431                         case PERM_COD_ASSIGN:
4432                                 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4433                                 if (rc != ASSIGN_OK) break;
4434                                 sig_req(plci, CALL_REQ, 0);
4435                                 send_req(plci);
4436                                 plci->internal_command = PERM_COD_CALL;
4437                                 return;
4438
4439                                 /* Null Call Reference Request pending */
4440                         case C_NCR_FAC_REQ:
4441                                 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4442                                 if (global_req == ASSIGN)
4443                                 {
4444                                         if (rc == ASSIGN_OK)
4445                                         {
4446                                                 return;
4447                                         }
4448                                         else
4449                                         {
4450                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4451                                                 appl->NullCREnable = false;
4452                                                 plci_remove(plci);
4453                                         }
4454                                 }
4455                                 else if (req == NCR_FACILITY)
4456                                 {
4457                                         if (rc == OK)
4458                                         {
4459                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4460                                         }
4461                                         else
4462                                         {
4463                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4464                                                 appl->NullCREnable = false;
4465                                         }
4466                                         plci_remove(plci);
4467                                 }
4468                                 break;
4469
4470                         case HOOK_ON_REQ:
4471                                 if (plci->channels)
4472                                 {
4473                                         if (a->ncci_state[ncci] == CONNECTED)
4474                                         {
4475                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4476                                                 cleanup_ncci_data(plci, ncci);
4477                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
4478                                         }
4479                                         break;
4480                                 }
4481                                 break;
4482
4483                         case HOOK_OFF_REQ:
4484                                 if (plci->State == INC_DIS_PENDING)
4485                                         break;
4486                                 sig_req(plci, CALL_REQ, 0);
4487                                 send_req(plci);
4488                                 plci->State = OUTG_CON_PENDING;
4489                                 break;
4490
4491
4492                         case MWI_ACTIVATE_REQ_PEND:
4493                         case MWI_DEACTIVATE_REQ_PEND:
4494                                 if (global_req == ASSIGN && rc == ASSIGN_OK)
4495                                 {
4496                                         dbug(1, dprintf("MWI_REQ assigned"));
4497                                         return;
4498                                 }
4499                                 else if (rc != OK)
4500                                 {
4501                                         if (rc == WRONG_IE)
4502                                         {
4503                                                 Info = 0x2007; /* Illegal message parameter coding */
4504                                                 dbug(1, dprintf("MWI_REQ invalid parameter"));
4505                                         }
4506                                         else
4507                                         {
4508                                                 Info = 0x300B; /* not supported */
4509                                                 dbug(1, dprintf("MWI_REQ not supported"));
4510                                         }
4511                                         /* 0x3010: Request not allowed in this state */
4512                                         PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4513
4514                                 }
4515                                 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4516                                 {
4517                                         PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4518                                 }
4519                                 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4520
4521                                 if (plci->cr_enquiry)
4522                                 {
4523                                         sendf(plci->appl,
4524                                               _FACILITY_R | CONFIRM,
4525                                               Id & 0xf,
4526                                               plci->number,
4527                                               "wws", Info, (word)3, SSparms);
4528                                         if (rc != OK) plci_remove(plci);
4529                                 }
4530                                 else
4531                                 {
4532                                         sendf(plci->appl,
4533                                               _FACILITY_R | CONFIRM,
4534                                               Id,
4535                                               plci->number,
4536                                               "wws", Info, (word)3, SSparms);
4537                                 }
4538                                 break;
4539
4540                         case CONF_BEGIN_REQ_PEND:
4541                         case CONF_ADD_REQ_PEND:
4542                         case CONF_SPLIT_REQ_PEND:
4543                         case CONF_DROP_REQ_PEND:
4544                         case CONF_ISOLATE_REQ_PEND:
4545                         case CONF_REATTACH_REQ_PEND:
4546                                 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4547                                 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4548                                 rplci = plci;
4549                                 rId = Id;
4550                                 switch (plci->internal_command)
4551                                 {
4552                                 case CONF_BEGIN_REQ_PEND:
4553                                         SSparms[1] = S_CONF_BEGIN;
4554                                         break;
4555                                 case CONF_ADD_REQ_PEND:
4556                                         SSparms[1] = S_CONF_ADD;
4557                                         rplci = plci->relatedPTYPLCI;
4558                                         rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4559                                         break;
4560                                 case CONF_SPLIT_REQ_PEND:
4561                                         SSparms[1] = S_CONF_SPLIT;
4562                                         break;
4563                                 case CONF_DROP_REQ_PEND:
4564                                         SSparms[1] = S_CONF_DROP;
4565                                         break;
4566                                 case CONF_ISOLATE_REQ_PEND:
4567                                         SSparms[1] = S_CONF_ISOLATE;
4568                                         break;
4569                                 case CONF_REATTACH_REQ_PEND:
4570                                         SSparms[1] = S_CONF_REATTACH;
4571                                         break;
4572                                 }
4573
4574                                 if (rc != OK)
4575                                 {
4576                                         Info = 0x300E; /* not supported */
4577                                         plci->relatedPTYPLCI = NULL;
4578                                         plci->ptyState = 0;
4579                                 }
4580                                 sendf(rplci->appl,
4581                                       _FACILITY_R | CONFIRM,
4582                                       rId,
4583                                       plci->number,
4584                                       "wws", Info, (word)3, SSparms);
4585                                 break;
4586
4587                         case VSWITCH_REQ_PEND:
4588                                 if (rc != OK)
4589                                 {
4590                                         if (plci->relatedPTYPLCI)
4591                                         {
4592                                                 plci->relatedPTYPLCI->vswitchstate = 0;
4593                                                 plci->relatedPTYPLCI->vsprot = 0;
4594                                                 plci->relatedPTYPLCI->vsprotdialect = 0;
4595                                         }
4596                                         plci->vswitchstate = 0;
4597                                         plci->vsprot = 0;
4598                                         plci->vsprotdialect = 0;
4599                                 }
4600                                 else
4601                                 {
4602                                         if (plci->relatedPTYPLCI &&
4603                                             plci->vswitchstate == 1 &&
4604                                             plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4605                                                 plci->vswitchstate = 3;
4606                                 }
4607                                 break;
4608
4609                                 /* Call Deflection Request pending (SSCT) */
4610                         case CD_REQ_PEND:
4611                                 SSparms[1] = S_CALL_DEFLECTION;
4612                                 if (rc != OK)
4613                                 {
4614                                         Info = 0x300E; /* not supported */
4615                                         plci->appl->CDEnable = 0;
4616                                 }
4617                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4618                                       plci->number, "wws", Info, (word)3, SSparms);
4619                                 break;
4620
4621                         case RTP_CONNECT_B3_REQ_COMMAND_2:
4622                                 if (rc == OK)
4623                                 {
4624                                         ncci = get_ncci(plci, ch, 0);
4625                                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4626                                         plci->channels++;
4627                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4628                                 }
4629
4630                         default:
4631                                 if (plci->internal_command_queue[0])
4632                                 {
4633                                         (*(plci->internal_command_queue[0]))(Id, plci, rc);
4634                                         if (plci->internal_command)
4635                                                 return;
4636                                 }
4637                                 break;
4638                         }
4639                         next_internal_command(Id, plci);
4640                 }
4641         }
4642         else /* appl==0 */
4643         {
4644                 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4645                 if (plci->tel) Id |= EXT_CONTROLLER;
4646
4647                 switch (plci->internal_command)
4648                 {
4649                 case BLOCK_PLCI:
4650                         return;
4651
4652                 case START_L1_SIG_ASSIGN_PEND:
4653                 case REM_L1_SIG_ASSIGN_PEND:
4654                         if (global_req == ASSIGN)
4655                         {
4656                                 break;
4657                         }
4658                         else
4659                         {
4660                                 dbug(1, dprintf("***L1 Req rem PLCI"));
4661                                 plci->internal_command = 0;
4662                                 sig_req(plci, REMOVE, 0);
4663                                 send_req(plci);
4664                         }
4665                         break;
4666
4667                         /* Call Deflection Request pending, just no appl ptr assigned */
4668                 case CD_REQ_PEND:
4669                         SSparms[1] = S_CALL_DEFLECTION;
4670                         if (rc != OK)
4671                         {
4672                                 Info = 0x300E; /* not supported */
4673                         }
4674                         for (i = 0; i < max_appl; i++)
4675                         {
4676                                 if (application[i].CDEnable)
4677                                 {
4678                                         if (!application[i].Id) application[i].CDEnable = 0;
4679                                         else
4680                                         {
4681                                                 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4682                                                       plci->number, "wws", Info, (word)3, SSparms);
4683                                                 if (Info) application[i].CDEnable = 0;
4684                                         }
4685                                 }
4686                         }
4687                         plci->internal_command = 0;
4688                         break;
4689
4690                 case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4691                         return;
4692
4693                 case PERM_COD_CALL:
4694                         plci->internal_command = PERM_COD_CONN_PEND;
4695                         dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4696                         return;
4697
4698                 case PERM_COD_ASSIGN:
4699                         dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4700                         plci->internal_command = 0;
4701                         if (rc != ASSIGN_OK) break;
4702                         plci->internal_command = PERM_COD_CALL;
4703                         sig_req(plci, CALL_REQ, 0);
4704                         send_req(plci);
4705                         return;
4706
4707                 case LISTEN_SIG_ASSIGN_PEND:
4708                         if (rc == ASSIGN_OK)
4709                         {
4710                                 plci->internal_command = 0;
4711                                 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4712                                 add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4713                                 sig_req(plci, INDICATE_REQ, 0);
4714                                 send_req(plci);
4715                         }
4716                         else
4717                         {
4718                                 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4719                                 a->listen_active--;
4720                                 plci_remove(plci);
4721                                 plci->State = IDLE;
4722                         }
4723                         break;
4724
4725                 case USELAW_REQ:
4726                         if (global_req == ASSIGN)
4727                         {
4728                                 if (rc == ASSIGN_OK)
4729                                 {
4730                                         sig_req(plci, LAW_REQ, 0);
4731                                         send_req(plci);
4732                                         dbug(1, dprintf("Auto-Law assigned"));
4733                                 }
4734                                 else
4735                                 {
4736                                         dbug(1, dprintf("Auto-Law assign failed"));
4737                                         a->automatic_law = 3;
4738                                         plci->internal_command = 0;
4739                                         a->automatic_lawPLCI = NULL;
4740                                 }
4741                                 break;
4742                         }
4743                         else if (req == LAW_REQ && rc == OK)
4744                         {
4745                                 dbug(1, dprintf("Auto-Law initiated"));
4746                                 a->automatic_law = 2;
4747                                 plci->internal_command = 0;
4748                         }
4749                         else
4750                         {
4751                                 dbug(1, dprintf("Auto-Law not supported"));
4752                                 a->automatic_law = 3;
4753                                 plci->internal_command = 0;
4754                                 sig_req(plci, REMOVE, 0);
4755                                 send_req(plci);
4756                                 a->automatic_lawPLCI = NULL;
4757                         }
4758                         break;
4759                 }
4760                 plci_remove_check(plci);
4761         }
4762 }
4763
4764 static void data_rc(PLCI *plci, byte ch)
4765 {
4766         dword Id;
4767         DIVA_CAPI_ADAPTER *a;
4768         NCCI *ncci_ptr;
4769         DATA_B3_DESC *data;
4770         word ncci;
4771
4772         if (plci->appl)
4773         {
4774                 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4775                 a = plci->adapter;
4776                 ncci = a->ch_ncci[ch];
4777                 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4778                 {
4779                         ncci_ptr = &(a->ncci[ncci]);
4780                         dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4781                         if (ncci_ptr->data_pending)
4782                         {
4783                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4784                                 if (!(data->Flags & 4) && a->ncci_state[ncci])
4785                                 {
4786                                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4787                                         if (plci->tel) Id |= EXT_CONTROLLER;
4788                                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4789                                               "ww", data->Handle, 0);
4790                                 }
4791                                 (ncci_ptr->data_out)++;
4792                                 if (ncci_ptr->data_out == MAX_DATA_B3)
4793                                         ncci_ptr->data_out = 0;
4794                                 (ncci_ptr->data_pending)--;
4795                         }
4796                 }
4797         }
4798 }
4799
4800 static void data_ack(PLCI *plci, byte ch)
4801 {
4802         dword Id;
4803         DIVA_CAPI_ADAPTER *a;
4804         NCCI *ncci_ptr;
4805         word ncci;
4806
4807         a = plci->adapter;
4808         ncci = a->ch_ncci[ch];
4809         ncci_ptr = &(a->ncci[ncci]);
4810         if (ncci_ptr->data_ack_pending)
4811         {
4812                 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4813                 {
4814                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4815                         if (plci->tel) Id |= EXT_CONTROLLER;
4816                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4817                               "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4818                 }
4819                 (ncci_ptr->data_ack_out)++;
4820                 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4821                         ncci_ptr->data_ack_out = 0;
4822                 (ncci_ptr->data_ack_pending)--;
4823         }
4824 }
4825
4826 static void sig_ind(PLCI *plci)
4827 {
4828         dword x_Id;
4829         dword Id;
4830         dword rId;
4831         word i;
4832         word cip;
4833         dword cip_mask;
4834         byte *ie;
4835         DIVA_CAPI_ADAPTER *a;
4836         API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4837 #define MAXPARMSIDS 31
4838         byte *parms[MAXPARMSIDS];
4839         byte *add_i[4];
4840         byte *multi_fac_parms[MAX_MULTI_IE];
4841         byte *multi_pi_parms[MAX_MULTI_IE];
4842         byte *multi_ssext_parms[MAX_MULTI_IE];
4843         byte *multi_CiPN_parms[MAX_MULTI_IE];
4844
4845         byte *multi_vswitch_parms[MAX_MULTI_IE];
4846
4847         byte ai_len;
4848         byte *esc_chi = "";
4849         byte *esc_law = "";
4850         byte *pty_cai = "";
4851         byte *esc_cr  = "";
4852         byte *esc_profile = "";
4853
4854         byte facility[256];
4855         PLCI *tplci = NULL;
4856         byte chi[] = "\x02\x18\x01";
4857         byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4858         byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4859         /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4860         /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4861         /* SMSG is situated at the end because its 0 (for compatibility reasons */
4862         /* (see Info_Mask Bit 4, first IE. then the message type)           */
4863         word parms_id[] =
4864                 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4865                  UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4866                  RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4867                  CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4868         /* 14 FTY repl by ESC_CHI */
4869         /* 18 PI  repl by ESC_LAW */
4870         /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4871         word multi_fac_id[] = {1, FTY};
4872         word multi_pi_id[]  = {1, PI};
4873         word multi_CiPN_id[]  = {1, OAD};
4874         word multi_ssext_id[]  = {1, ESC_SSEXT};
4875
4876         word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4877
4878         byte *cau;
4879         word ncci;
4880         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4881         byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4882         byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4883         byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4884         byte force_mt_info = false;
4885         byte dir;
4886         dword d;
4887         word w;
4888
4889         a = plci->adapter;
4890         Id = ((word)plci->Id << 8) | a->Id;
4891         PUT_WORD(&SS_Ind[4], 0x0000);
4892
4893         if (plci->sig_remove_id)
4894         {
4895                 plci->Sig.RNR = 2; /* discard */
4896                 dbug(1, dprintf("SIG discard while remove pending"));
4897                 return;
4898         }
4899         if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4900         dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4901                         Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4902         if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4903         {
4904                 plci->Sig.RNR = 1;
4905                 return;
4906         }
4907         if (plci->Sig.Ind == HANGUP && plci->channels)
4908         {
4909                 plci->Sig.RNR = 1;
4910                 plci->hangup_flow_ctrl_timer++;
4911                 /* recover the network layer after timeout */
4912                 if (plci->hangup_flow_ctrl_timer == 100)
4913                 {
4914                         dbug(1, dprintf("Exceptional disc"));
4915                         plci->Sig.RNR = 0;
4916                         plci->hangup_flow_ctrl_timer = 0;
4917                         for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4918                         {
4919                                 if (a->ncci_plci[ncci] == plci->Id)
4920                                 {
4921                                         cleanup_ncci_data(plci, ncci);
4922                                         if (plci->channels)plci->channels--;
4923                                         if (plci->appl)
4924                                                 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4925                                 }
4926                         }
4927                         if (plci->appl)
4928                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4929                         plci_remove(plci);
4930                         plci->State = IDLE;
4931                 }
4932                 return;
4933         }
4934
4935         /* do first parse the info with no OAD in, because OAD will be converted */
4936         /* first the multiple facility IE, then mult. progress ind.              */
4937         /* then the parameters for the info_ind + conn_ind                       */
4938         IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4939         IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4940         IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4941
4942         IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4943
4944         IndParse(plci, parms_id, parms, 0);
4945         IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4946         esc_chi  = parms[14];
4947         esc_law  = parms[18];
4948         pty_cai  = parms[24];
4949         esc_cr   = parms[25];
4950         esc_profile = parms[27];
4951         if (esc_cr[0] && plci)
4952         {
4953                 if (plci->cr_enquiry && plci->appl)
4954                 {
4955                         plci->cr_enquiry = false;
4956                         /* d = MANU_ID            */
4957                         /* w = m_command          */
4958                         /* b = total length       */
4959                         /* b = indication type    */
4960                         /* b = length of all IEs  */
4961                         /* b = IE1                */
4962                         /* S = IE1 length + cont. */
4963                         /* b = IE2                */
4964                         /* S = IE2 length + cont. */
4965                         sendf(plci->appl,
4966                               _MANUFACTURER_I,
4967                               Id,
4968                               0,
4969                               "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4970                               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);
4971                 }
4972         }
4973         /* create the additional info structure                                  */
4974         add_i[1] = parms[15]; /* KEY of additional info */
4975         add_i[2] = parms[11]; /* UUI of additional info */
4976         ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4977
4978         /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4979         /* indication returns by the card if requested by the function           */
4980         /* AutomaticLaw() after driver init                                      */
4981         if (a->automatic_law < 4)
4982         {
4983                 if (esc_law[0]) {
4984                         if (esc_law[2]) {
4985                                 dbug(0, dprintf("u-Law selected"));
4986                                 a->u_law = 1;
4987                         }
4988                         else {
4989                                 dbug(0, dprintf("a-Law selected"));
4990                                 a->u_law = 0;
4991                         }
4992                         a->automatic_law = 4;
4993                         if (plci == a->automatic_lawPLCI) {
4994                                 plci->internal_command = 0;
4995                                 sig_req(plci, REMOVE, 0);
4996                                 send_req(plci);
4997                                 a->automatic_lawPLCI = NULL;
4998                         }
4999                 }
5000                 if (esc_profile[0])
5001                 {
5002                         dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5003                                         UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5004                                         GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5005                                         GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5006
5007                         a->profile.Global_Options &= 0x000000ffL;
5008                         a->profile.B1_Protocols &= 0x000003ffL;
5009                         a->profile.B2_Protocols &= 0x00001fdfL;
5010                         a->profile.B3_Protocols &= 0x000000b7L;
5011
5012                         a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5013                                 GL_BCHANNEL_OPERATION_SUPPORTED;
5014                         a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5015                         a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5016                         a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5017                         a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5018                         a->man_profile.private_options = 0;
5019
5020                         if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5021                         {
5022                                 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5023                                 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5024                         }
5025
5026
5027                         if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5028                                 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5029                         a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5030                         a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031
5032
5033                         if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5034                                 a->man_profile.private_options |= 1L << PRIVATE_T38;
5035
5036
5037                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5038                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5039
5040
5041                         if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5042                                 a->man_profile.private_options |= 1L << PRIVATE_V18;
5043
5044
5045                         if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5046                                 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5047
5048
5049                         if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5050                                 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5051
5052
5053                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5054                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5055
5056
5057                         if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5058                                 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5059
5060
5061                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5062                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5063
5064                 }
5065                 else
5066                 {
5067                         a->profile.Global_Options &= 0x0000007fL;
5068                         a->profile.B1_Protocols &= 0x000003dfL;
5069                         a->profile.B2_Protocols &= 0x00001adfL;
5070                         a->profile.B3_Protocols &= 0x000000b7L;
5071                         a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5072                 }
5073                 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5074                                                 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5075                 {
5076                         a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5077                 }
5078                 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5079                 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5080                                 UnMapController(a->Id), a->profile.Global_Options,
5081                                 a->profile.B1_Protocols, a->profile.B2_Protocols,
5082                                 a->profile.B3_Protocols, a->manufacturer_features));
5083         }
5084         /* codec plci for the handset/hook state support is just an internal id  */
5085         if (plci != a->AdvCodecPLCI)
5086         {
5087                 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5088                 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5089                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5090                 SendInfo(plci, Id, parms, force_mt_info);
5091
5092                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5093
5094         }
5095
5096         /* switch the codec to the b-channel                                     */
5097         if (esc_chi[0] && plci && !plci->SuppState) {
5098                 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5099                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5100                 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5101                 if (plci->tel == ADV_VOICE && plci->appl) {
5102                         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5103                 }
5104         }
5105
5106         if (plci->appl) plci->appl->Number++;
5107
5108         switch (plci->Sig.Ind) {
5109                 /* Response to Get_Supported_Services request */
5110         case S_SUPPORTED:
5111                 dbug(1, dprintf("S_Supported"));
5112                 if (!plci->appl) break;
5113                 if (pty_cai[0] == 4)
5114                 {
5115                         PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5116                 }
5117                 else
5118                 {
5119                         PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5120                 }
5121                 PUT_WORD(&CF_Ind[1], 0);
5122                 PUT_WORD(&CF_Ind[4], 0);
5123                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5124                 plci_remove(plci);
5125                 break;
5126
5127                 /* Supplementary Service rejected */
5128         case S_SERVICE_REJ:
5129                 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5130                 if (!pty_cai[0]) break;
5131                 switch (pty_cai[5])
5132                 {
5133                 case ECT_EXECUTE:
5134                 case THREE_PTY_END:
5135                 case THREE_PTY_BEGIN:
5136                         if (!plci->relatedPTYPLCI) break;
5137                         tplci = plci->relatedPTYPLCI;
5138                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5139                         if (tplci->tel) rId |= EXT_CONTROLLER;
5140                         if (pty_cai[5] == ECT_EXECUTE)
5141                         {
5142                                 PUT_WORD(&SS_Ind[1], S_ECT);
5143
5144                                 plci->vswitchstate = 0;
5145                                 plci->relatedPTYPLCI->vswitchstate = 0;
5146
5147                         }
5148                         else
5149                         {
5150                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5151                         }
5152                         if (pty_cai[2] != 0xff)
5153                         {
5154                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5155                         }
5156                         else
5157                         {
5158                                 PUT_WORD(&SS_Ind[4], 0x300E);
5159                         }
5160                         plci->relatedPTYPLCI = NULL;
5161                         plci->ptyState = 0;
5162                         sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5163                         break;
5164
5165                 case CALL_DEFLECTION:
5166                         if (pty_cai[2] != 0xff)
5167                         {
5168                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5169                         }
5170                         else
5171                         {
5172                                 PUT_WORD(&SS_Ind[4], 0x300E);
5173                         }
5174                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5175                         for (i = 0; i < max_appl; i++)
5176                         {
5177                                 if (application[i].CDEnable)
5178                                 {
5179                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5180                                         application[i].CDEnable = false;
5181                                 }
5182                         }
5183                         break;
5184
5185                 case DEACTIVATION_DIVERSION:
5186                 case ACTIVATION_DIVERSION:
5187                 case DIVERSION_INTERROGATE_CFU:
5188                 case DIVERSION_INTERROGATE_CFB:
5189                 case DIVERSION_INTERROGATE_CFNR:
5190                 case DIVERSION_INTERROGATE_NUM:
5191                 case CCBS_REQUEST:
5192                 case CCBS_DEACTIVATE:
5193                 case CCBS_INTERROGATE:
5194                         if (!plci->appl) break;
5195                         if (pty_cai[2] != 0xff)
5196                         {
5197                                 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5198                         }
5199                         else
5200                         {
5201                                 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5202                         }
5203                         switch (pty_cai[5])
5204                         {
5205                         case DEACTIVATION_DIVERSION:
5206                                 dbug(1, dprintf("Deact_Div"));
5207                                 Interr_Err_Ind[0] = 0x9;
5208                                 Interr_Err_Ind[3] = 0x6;
5209                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5210                                 break;
5211                         case ACTIVATION_DIVERSION:
5212                                 dbug(1, dprintf("Act_Div"));
5213                                 Interr_Err_Ind[0] = 0x9;
5214                                 Interr_Err_Ind[3] = 0x6;
5215                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5216                                 break;
5217                         case DIVERSION_INTERROGATE_CFU:
5218                         case DIVERSION_INTERROGATE_CFB:
5219                         case DIVERSION_INTERROGATE_CFNR:
5220                                 dbug(1, dprintf("Interr_Div"));
5221                                 Interr_Err_Ind[0] = 0xa;
5222                                 Interr_Err_Ind[3] = 0x7;
5223                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5224                                 break;
5225                         case DIVERSION_INTERROGATE_NUM:
5226                                 dbug(1, dprintf("Interr_Num"));
5227                                 Interr_Err_Ind[0] = 0xa;
5228                                 Interr_Err_Ind[3] = 0x7;
5229                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5230                                 break;
5231                         case CCBS_REQUEST:
5232                                 dbug(1, dprintf("CCBS Request"));
5233                                 Interr_Err_Ind[0] = 0xd;
5234                                 Interr_Err_Ind[3] = 0xa;
5235                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5236                                 break;
5237                         case CCBS_DEACTIVATE:
5238                                 dbug(1, dprintf("CCBS Deactivate"));
5239                                 Interr_Err_Ind[0] = 0x9;
5240                                 Interr_Err_Ind[3] = 0x6;
5241                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5242                                 break;
5243                         case CCBS_INTERROGATE:
5244                                 dbug(1, dprintf("CCBS Interrogate"));
5245                                 Interr_Err_Ind[0] = 0xb;
5246                                 Interr_Err_Ind[3] = 0x8;
5247                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5248                                 break;
5249                         }
5250                         PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5251                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5252                         plci_remove(plci);
5253                         break;
5254                 case ACTIVATION_MWI:
5255                 case DEACTIVATION_MWI:
5256                         if (pty_cai[5] == ACTIVATION_MWI)
5257                         {
5258                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5259                         }
5260                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5261
5262                         if (pty_cai[2] != 0xff)
5263                         {
5264                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5265                         }
5266                         else
5267                         {
5268                                 PUT_WORD(&SS_Ind[4], 0x300E);
5269                         }
5270
5271                         if (plci->cr_enquiry)
5272                         {
5273                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5274                                 plci_remove(plci);
5275                         }
5276                         else
5277                         {
5278                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5279                         }
5280                         break;
5281                 case CONF_ADD: /* ERROR */
5282                 case CONF_BEGIN:
5283                 case CONF_DROP:
5284                 case CONF_ISOLATE:
5285                 case CONF_REATTACH:
5286                         CONF_Ind[0] = 9;
5287                         CONF_Ind[3] = 6;
5288                         switch (pty_cai[5])
5289                         {
5290                         case CONF_BEGIN:
5291                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5292                                 plci->ptyState = 0;
5293                                 break;
5294                         case CONF_DROP:
5295                                 CONF_Ind[0] = 5;
5296                                 CONF_Ind[3] = 2;
5297                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5298                                 plci->ptyState = CONNECTED;
5299                                 break;
5300                         case CONF_ISOLATE:
5301                                 CONF_Ind[0] = 5;
5302                                 CONF_Ind[3] = 2;
5303                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5304                                 plci->ptyState = CONNECTED;
5305                                 break;
5306                         case CONF_REATTACH:
5307                                 CONF_Ind[0] = 5;
5308                                 CONF_Ind[3] = 2;
5309                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5310                                 plci->ptyState = CONNECTED;
5311                                 break;
5312                         case CONF_ADD:
5313                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5314                                 plci->relatedPTYPLCI = NULL;
5315                                 tplci = plci->relatedPTYPLCI;
5316                                 if (tplci) tplci->ptyState = CONNECTED;
5317                                 plci->ptyState = CONNECTED;
5318                                 break;
5319                         }
5320
5321                         if (pty_cai[2] != 0xff)
5322                         {
5323                                 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5324                         }
5325                         else
5326                         {
5327                                 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5328                                                                   within the required time */
5329                         }
5330
5331                         PUT_DWORD(&CONF_Ind[6], 0x0);
5332                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5333                         break;
5334                 }
5335                 break;
5336
5337                 /* Supplementary Service indicates success */
5338         case S_SERVICE:
5339                 dbug(1, dprintf("Service_Ind"));
5340                 PUT_WORD(&CF_Ind[4], 0);
5341                 switch (pty_cai[5])
5342                 {
5343                 case THREE_PTY_END:
5344                 case THREE_PTY_BEGIN:
5345                 case ECT_EXECUTE:
5346                         if (!plci->relatedPTYPLCI) break;
5347                         tplci = plci->relatedPTYPLCI;
5348                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5349                         if (tplci->tel) rId |= EXT_CONTROLLER;
5350                         if (pty_cai[5] == ECT_EXECUTE)
5351                         {
5352                                 PUT_WORD(&SS_Ind[1], S_ECT);
5353
5354                                 if (plci->vswitchstate != 3)
5355                                 {
5356
5357                                         plci->ptyState = IDLE;
5358                                         plci->relatedPTYPLCI = NULL;
5359                                         plci->ptyState = 0;
5360
5361                                 }
5362
5363                                 dbug(1, dprintf("ECT OK"));
5364                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5365
5366
5367
5368                         }
5369                         else
5370                         {
5371                                 switch (plci->ptyState)
5372                                 {
5373                                 case S_3PTY_BEGIN:
5374                                         plci->ptyState = CONNECTED;
5375                                         dbug(1, dprintf("3PTY ON"));
5376                                         break;
5377
5378                                 case S_3PTY_END:
5379                                         plci->ptyState = IDLE;
5380                                         plci->relatedPTYPLCI = NULL;
5381                                         plci->ptyState = 0;
5382                                         dbug(1, dprintf("3PTY OFF"));
5383                                         break;
5384                                 }
5385                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5386                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5387                         }
5388                         break;
5389
5390                 case CALL_DEFLECTION:
5391                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5392                         for (i = 0; i < max_appl; i++)
5393                         {
5394                                 if (application[i].CDEnable)
5395                                 {
5396                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5397                                         application[i].CDEnable = false;
5398                                 }
5399                         }
5400                         break;
5401
5402                 case DEACTIVATION_DIVERSION:
5403                 case ACTIVATION_DIVERSION:
5404                         if (!plci->appl) break;
5405                         PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5406                         PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5407                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5408                         plci_remove(plci);
5409                         break;
5410
5411                 case DIVERSION_INTERROGATE_CFU:
5412                 case DIVERSION_INTERROGATE_CFB:
5413                 case DIVERSION_INTERROGATE_CFNR:
5414                 case DIVERSION_INTERROGATE_NUM:
5415                 case CCBS_REQUEST:
5416                 case CCBS_DEACTIVATE:
5417                 case CCBS_INTERROGATE:
5418                         if (!plci->appl) break;
5419                         switch (pty_cai[5])
5420                         {
5421                         case DIVERSION_INTERROGATE_CFU:
5422                         case DIVERSION_INTERROGATE_CFB:
5423                         case DIVERSION_INTERROGATE_CFNR:
5424                                 dbug(1, dprintf("Interr_Div"));
5425                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5426                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5427                                 break;
5428                         case DIVERSION_INTERROGATE_NUM:
5429                                 dbug(1, dprintf("Interr_Num"));
5430                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5431                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5432                                 break;
5433                         case CCBS_REQUEST:
5434                                 dbug(1, dprintf("CCBS Request"));
5435                                 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5436                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5437                                 break;
5438                         case CCBS_DEACTIVATE:
5439                                 dbug(1, dprintf("CCBS Deactivate"));
5440                                 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5441                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5442                                 break;
5443                         case CCBS_INTERROGATE:
5444                                 dbug(1, dprintf("CCBS Interrogate"));
5445                                 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5446                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5447                                 break;
5448                         }
5449                         PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5450                         PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5451                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5452                         plci_remove(plci);
5453                         break;
5454
5455                 case ACTIVATION_MWI:
5456                 case DEACTIVATION_MWI:
5457                         if (pty_cai[5] == ACTIVATION_MWI)
5458                         {
5459                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5460                         }
5461                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5462                         if (plci->cr_enquiry)
5463                         {
5464                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5465                                 plci_remove(plci);
5466                         }
5467                         else
5468                         {
5469                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5470                         }
5471                         break;
5472                 case MWI_INDICATION:
5473                         if (pty_cai[0] >= 0x12)
5474                         {
5475                                 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5476                                 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5477                                 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5478                                 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5479                                 {
5480                                         if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5481                                         {
5482                                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5483                                                 plci_remove(plci);
5484                                                 return;
5485                                         }
5486                                         else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5487                                         pty_cai[0] = 0;
5488                                 }
5489                                 else
5490                                 {
5491                                         for (i = 0; i < max_appl; i++)
5492                                         {
5493                                                 if (a->Notification_Mask[i]&SMASK_MWI)
5494                                                 {
5495                                                         sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5496                                                         pty_cai[0] = 0;
5497                                                 }
5498                                         }
5499                                 }
5500
5501                                 if (!pty_cai[0])
5502                                 { /* acknowledge */
5503                                         facility[2] = 0; /* returncode */
5504                                 }
5505                                 else facility[2] = 0xff;
5506                         }
5507                         else
5508                         {
5509                                 /* reject */
5510                                 facility[2] = 0xff; /* returncode */
5511                         }
5512                         facility[0] = 2;
5513                         facility[1] = MWI_RESPONSE; /* Function */
5514                         add_p(plci, CAI, facility);
5515                         add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5516                         sig_req(plci, S_SERVICE, 0);
5517                         send_req(plci);
5518                         plci->command = 0;
5519                         next_internal_command(Id, plci);
5520                         break;
5521                 case CONF_ADD: /* OK */
5522                 case CONF_BEGIN:
5523                 case CONF_DROP:
5524                 case CONF_ISOLATE:
5525                 case CONF_REATTACH:
5526                 case CONF_PARTYDISC:
5527                         CONF_Ind[0] = 9;
5528                         CONF_Ind[3] = 6;
5529                         switch (pty_cai[5])
5530                         {
5531                         case CONF_BEGIN:
5532                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5533                                 if (pty_cai[0] == 6)
5534                                 {
5535                                         d = pty_cai[6];
5536                                         PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5537                                 }
5538                                 else
5539                                 {
5540                                         PUT_DWORD(&CONF_Ind[6], 0x0);
5541                                 }
5542                                 break;
5543                         case CONF_ISOLATE:
5544                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5545                                 CONF_Ind[0] = 5;
5546                                 CONF_Ind[3] = 2;
5547                                 break;
5548                         case CONF_REATTACH:
5549                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5550                                 CONF_Ind[0] = 5;
5551                                 CONF_Ind[3] = 2;
5552                                 break;
5553                         case CONF_DROP:
5554                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5555                                 CONF_Ind[0] = 5;
5556                                 CONF_Ind[3] = 2;
5557                                 break;
5558                         case CONF_ADD:
5559                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5560                                 d = pty_cai[6];
5561                                 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5562                                 tplci = plci->relatedPTYPLCI;
5563                                 if (tplci) tplci->ptyState = CONNECTED;
5564                                 break;
5565                         case CONF_PARTYDISC:
5566                                 CONF_Ind[0] = 7;
5567                                 CONF_Ind[3] = 4;
5568                                 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5569                                 d = pty_cai[6];
5570                                 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5571                                 break;
5572                         }
5573                         plci->ptyState = CONNECTED;
5574                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5575                         break;
5576                 case CCBS_INFO_RETAIN:
5577                 case CCBS_ERASECALLLINKAGEID:
5578                 case CCBS_STOP_ALERTING:
5579                         CONF_Ind[0] = 5;
5580                         CONF_Ind[3] = 2;
5581                         switch (pty_cai[5])
5582                         {
5583                         case CCBS_INFO_RETAIN:
5584                                 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5585                                 break;
5586                         case CCBS_STOP_ALERTING:
5587                                 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5588                                 break;
5589                         case CCBS_ERASECALLLINKAGEID:
5590                                 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5591                                 CONF_Ind[0] = 7;
5592                                 CONF_Ind[3] = 4;
5593                                 CONF_Ind[6] = 0;
5594                                 CONF_Ind[7] = 0;
5595                                 break;
5596                         }
5597                         w = pty_cai[6];
5598                         PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5599
5600                         if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5601                         {
5602                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5603                         }
5604                         else
5605                         {
5606                                 for (i = 0; i < max_appl; i++)
5607                                         if (a->Notification_Mask[i] & SMASK_CCBS)
5608                                                 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5609                         }
5610                         break;
5611                 }
5612                 break;
5613         case CALL_HOLD_REJ:
5614                 cau = parms[7];
5615                 if (cau)
5616                 {
5617                         i = _L3_CAUSE | cau[2];
5618                         if (cau[2] == 0) i = 0x3603;
5619                 }
5620                 else
5621                 {
5622                         i = 0x3603;
5623                 }
5624                 PUT_WORD(&SS_Ind[1], S_HOLD);
5625                 PUT_WORD(&SS_Ind[4], i);
5626                 if (plci->SuppState == HOLD_REQUEST)
5627                 {
5628                         plci->SuppState = IDLE;
5629                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5630                 }
5631                 break;
5632
5633         case CALL_HOLD_ACK:
5634                 if (plci->SuppState == HOLD_REQUEST)
5635                 {
5636                         plci->SuppState = CALL_HELD;
5637                         CodecIdCheck(a, plci);
5638                         start_internal_command(Id, plci, hold_save_command);
5639                 }
5640                 break;
5641
5642         case CALL_RETRIEVE_REJ:
5643                 cau = parms[7];
5644                 if (cau)
5645                 {
5646                         i = _L3_CAUSE | cau[2];
5647                         if (cau[2] == 0) i = 0x3603;
5648                 }
5649                 else
5650                 {
5651                         i = 0x3603;
5652                 }
5653                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5654                 PUT_WORD(&SS_Ind[4], i);
5655                 if (plci->SuppState == RETRIEVE_REQUEST)
5656                 {
5657                         plci->SuppState = CALL_HELD;
5658                         CodecIdCheck(a, plci);
5659                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5660                 }
5661                 break;
5662
5663         case CALL_RETRIEVE_ACK:
5664                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5665                 if (plci->SuppState == RETRIEVE_REQUEST)
5666                 {
5667                         plci->SuppState = IDLE;
5668                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5669                         plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5670                         if (plci->tel)
5671                         {
5672                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5673                                 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5674                                 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5675                                 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5676                                 {
5677                                         dbug(1, dprintf("Get B-ch"));
5678                                         start_internal_command(Id, plci, retrieve_restore_command);
5679                                 }
5680                                 else
5681                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5682                         }
5683                         else
5684                                 start_internal_command(Id, plci, retrieve_restore_command);
5685                 }
5686                 break;
5687
5688         case INDICATE_IND:
5689                 if (plci->State != LISTENING) {
5690                         sig_req(plci, HANGUP, 0);
5691                         send_req(plci);
5692                         break;
5693                 }
5694                 cip = find_cip(a, parms[4], parms[6]);
5695                 cip_mask = 1L << cip;
5696                 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5697                 clear_c_ind_mask(plci);
5698                 if (!remove_started && !a->adapter_disabled)
5699                 {
5700                         set_c_ind_mask_bit(plci, MAX_APPL);
5701                         group_optimization(a, plci);
5702                         for (i = 0; i < max_appl; i++) {
5703                                 if (application[i].Id
5704                                     && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5705                                     && CPN_filter_ok(parms[0], a, i)
5706                                     && test_group_ind_mask_bit(plci, i)) {
5707                                         dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5708                                         set_c_ind_mask_bit(plci, i);
5709                                         dump_c_ind_mask(plci);
5710                                         plci->State = INC_CON_PENDING;
5711                                         plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5712                                                 CALL_DIR_IN | CALL_DIR_ANSWER;
5713                                         if (esc_chi[0]) {
5714                                                 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5715                                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5716                                         }
5717                                         /* if a listen on the ext controller is done, check if hook states */
5718                                         /* are supported or if just a on board codec must be activated     */
5719                                         if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5720                                                 if (a->profile.Global_Options & HANDSET)
5721                                                         plci->tel = ADV_VOICE;
5722                                                 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5723                                                         plci->tel = CODEC;
5724                                                 if (plci->tel) Id |= EXT_CONTROLLER;
5725                                                 a->codec_listen[i] = plci;
5726                                         }
5727
5728                                         sendf(&application[i], _CONNECT_I, Id, 0,
5729                                               "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5730                                               parms[0],    /* CalledPartyNumber   */
5731                                               multi_CiPN_parms[0],    /* CallingPartyNumber  */
5732                                               parms[2],    /* CalledPartySubad    */
5733                                               parms[3],    /* CallingPartySubad   */
5734                                               parms[4],    /* BearerCapability    */
5735                                               parms[5],    /* LowLC               */
5736                                               parms[6],    /* HighLC              */
5737                                               ai_len,      /* nested struct add_i */
5738                                               add_i[0],    /* B channel info    */
5739                                               add_i[1],    /* keypad facility   */
5740                                               add_i[2],    /* user user data    */
5741                                               add_i[3],    /* nested facility   */
5742                                               multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5743                                                 );
5744                                         SendSSExtInd(&application[i],
5745                                                      plci,
5746                                                      Id,
5747                                                      multi_ssext_parms);
5748                                         SendSetupInfo(&application[i],
5749                                                       plci,
5750                                                       Id,
5751                                                       parms,
5752                                                       SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753                                 }
5754                         }
5755                         clear_c_ind_mask_bit(plci, MAX_APPL);
5756                         dump_c_ind_mask(plci);
5757                 }
5758                 if (c_ind_mask_empty(plci)) {
5759                         sig_req(plci, HANGUP, 0);
5760                         send_req(plci);
5761                         plci->State = IDLE;
5762                 }
5763                 plci->notifiedcall = 0;
5764                 a->listen_active--;
5765                 listen_check(a);
5766                 break;
5767
5768         case CALL_PEND_NOTIFY:
5769                 plci->notifiedcall = 1;
5770                 listen_check(a);
5771                 break;
5772
5773         case CALL_IND:
5774         case CALL_CON:
5775                 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5776                 {
5777                         if (plci->internal_command == PERM_COD_CONN_PEND)
5778                         {
5779                                 if (plci->State == ADVANCED_VOICE_NOSIG)
5780                                 {
5781                                         dbug(1, dprintf("***Codec OK"));
5782                                         if (a->AdvSignalPLCI)
5783                                         {
5784                                                 tplci = a->AdvSignalPLCI;
5785                                                 if (tplci->spoofed_msg)
5786                                                 {
5787                                                         dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5788                                                         tplci->command = 0;
5789                                                         tplci->internal_command = 0;
5790                                                         x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5791                                                         switch (tplci->spoofed_msg)
5792                                                         {
5793                                                         case CALL_RES:
5794                                                                 tplci->command = _CONNECT_I | RESPONSE;
5795                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5796                                                                 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5797                                                                 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5798                                                                 {
5799                                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5800                                                                         add_p(tplci, LLI, "\x01\x01");
5801                                                                 }
5802                                                                 add_s(tplci, CONN_NR, &saved_parms[2]);
5803                                                                 add_s(tplci, LLC, &saved_parms[4]);
5804                                                                 add_ai(tplci, &saved_parms[5]);
5805                                                                 tplci->State = INC_CON_ACCEPT;
5806                                                                 sig_req(tplci, CALL_RES, 0);
5807                                                                 send_req(tplci);
5808                                                                 break;
5809
5810                                                         case AWAITING_SELECT_B:
5811                                                                 dbug(1, dprintf("Select_B continue"));
5812                                                                 start_internal_command(x_Id, tplci, select_b_command);
5813                                                                 break;
5814
5815                                                         case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5816                                                                 if (!tplci->Sig.Id)
5817                                                                 {
5818                                                                         dbug(1, dprintf("No SigID!"));
5819                                                                         sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5820                                                                         plci_remove(tplci);
5821                                                                         break;
5822                                                                 }
5823                                                                 tplci->command = _MANUFACTURER_R;
5824                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5825                                                                 dir = saved_parms[2].info[0];
5826                                                                 if (dir == 1) {
5827                                                                         sig_req(tplci, CALL_REQ, 0);
5828                                                                 }
5829                                                                 else if (!dir) {
5830                                                                         sig_req(tplci, LISTEN_REQ, 0);
5831                                                                 }
5832                                                                 send_req(tplci);
5833                                                                 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5834                                                                 break;
5835
5836                                                         case (CALL_REQ | AWAITING_MANUF_CON):
5837                                                                 sig_req(tplci, CALL_REQ, 0);
5838                                                                 send_req(tplci);
5839                                                                 break;
5840
5841                                                         case CALL_REQ:
5842                                                                 if (!tplci->Sig.Id)
5843                                                                 {
5844                                                                         dbug(1, dprintf("No SigID!"));
5845                                                                         sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5846                                                                         plci_remove(tplci);
5847                                                                         break;
5848                                                                 }
5849                                                                 tplci->command = _CONNECT_R;
5850                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5851                                                                 add_s(tplci, CPN, &saved_parms[1]);
5852                                                                 add_s(tplci, DSA, &saved_parms[3]);
5853                                                                 add_ai(tplci, &saved_parms[9]);
5854                                                                 sig_req(tplci, CALL_REQ, 0);
5855                                                                 send_req(tplci);
5856                                                                 break;
5857
5858                                                         case CALL_RETRIEVE:
5859                                                                 tplci->command = C_RETRIEVE_REQ;
5860                                                                 sig_req(tplci, CALL_RETRIEVE, 0);
5861                                                                 send_req(tplci);
5862                                                                 break;
5863                                                         }
5864                                                         tplci->spoofed_msg = 0;
5865                                                         if (tplci->internal_command == 0)
5866                                                                 next_internal_command(x_Id, tplci);
5867                                                 }
5868                                         }
5869                                         next_internal_command(Id, plci);
5870                                         break;
5871                                 }
5872                                 dbug(1, dprintf("***Codec Hook Init Req"));
5873                                 plci->internal_command = PERM_COD_HOOK;
5874                                 add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5875                                 sig_req(plci, TEL_CTRL, 0);
5876                                 send_req(plci);
5877                         }
5878                 }
5879                 else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5880                          && plci->State != INC_ACT_PENDING)
5881                 {
5882                         mixer_set_bchannel_id_esc(plci, plci->b_channel);
5883                         if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5884                         {
5885                                 chi[2] = plci->b_channel;
5886                                 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5887                         }
5888                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5889                         plci->State = INC_ACT_PENDING;
5890                 }
5891                 break;
5892
5893         case TEL_CTRL:
5894                 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5895                 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5896                         switch (ie[1] & 0x91) {
5897                         case 0x80:   /* hook off */
5898                         case 0x81:
5899                                 if (plci->internal_command == PERM_COD_HOOK)
5900                                 {
5901                                         dbug(1, dprintf("init:hook_off"));
5902                                         plci->hook_state = ie[1];
5903                                         next_internal_command(Id, plci);
5904                                         break;
5905                                 }
5906                                 else /* ignore doubled hook indications */
5907                                 {
5908                                         if (((plci->hook_state) & 0xf0) == 0x80)
5909                                         {
5910                                                 dbug(1, dprintf("ignore hook"));
5911                                                 break;
5912                                         }
5913                                         plci->hook_state = ie[1]&0x91;
5914                                 }
5915                                 /* check for incoming call pending */
5916                                 /* and signal '+'.Appl must decide */
5917                                 /* with connect_res if call must   */
5918                                 /* accepted or not                 */
5919                                 for (i = 0, tplci = NULL; i < max_appl; i++) {
5920                                         if (a->codec_listen[i]
5921                                             && (a->codec_listen[i]->State == INC_CON_PENDING
5922                                                 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5923                                                 tplci = a->codec_listen[i];
5924                                                 tplci->appl = &application[i];
5925                                         }
5926                                 }
5927                                 /* no incoming call, do outgoing call */
5928                                 /* and signal '+' if outg. setup   */
5929                                 if (!a->AdvSignalPLCI && !tplci) {
5930                                         if ((i = get_plci(a))) {
5931                                                 a->AdvSignalPLCI = &a->plci[i - 1];
5932                                                 tplci = a->AdvSignalPLCI;
5933                                                 tplci->tel  = ADV_VOICE;
5934                                                 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5935                                                 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5936                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5937                                                         add_p(tplci, LLI, "\x01\x01");
5938                                                 }
5939                                                 add_p(tplci, CAI, voice_cai);
5940                                                 add_p(tplci, OAD, a->TelOAD);
5941                                                 add_p(tplci, OSA, a->TelOSA);
5942                                                 add_p(tplci, SHIFT | 6, NULL);
5943                                                 add_p(tplci, SIN, "\x02\x01\x00");
5944                                                 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5945                                                 sig_req(tplci, ASSIGN, DSIG_ID);
5946                                                 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5947                                                 a->AdvSignalPLCI->command = 0;
5948                                                 tplci->appl = a->AdvSignalAppl;
5949                                                 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5950                                                 send_req(tplci);
5951                                         }
5952
5953                                 }
5954
5955                                 if (!tplci) break;
5956                                 Id = ((word)tplci->Id << 8) | a->Id;
5957                                 Id |= EXT_CONTROLLER;
5958                                 sendf(tplci->appl,
5959                                       _FACILITY_I,
5960                                       Id,
5961                                       0,
5962                                       "ws", (word)0, "\x01+");
5963                                 break;
5964
5965                         case 0x90:   /* hook on  */
5966                         case 0x91:
5967                                 if (plci->internal_command == PERM_COD_HOOK)
5968                                 {
5969                                         dbug(1, dprintf("init:hook_on"));
5970                                         plci->hook_state = ie[1] & 0x91;
5971                                         next_internal_command(Id, plci);
5972                                         break;
5973                                 }
5974                                 else /* ignore doubled hook indications */
5975                                 {
5976                                         if (((plci->hook_state) & 0xf0) == 0x90) break;
5977                                         plci->hook_state = ie[1] & 0x91;
5978                                 }
5979                                 /* hangup the adv. voice call and signal '-' to the appl */
5980                                 if (a->AdvSignalPLCI) {
5981                                         Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5982                                         if (plci->tel) Id |= EXT_CONTROLLER;
5983                                         sendf(a->AdvSignalAppl,
5984                                               _FACILITY_I,
5985                                               Id,
5986                                               0,
5987                                               "ws", (word)0, "\x01-");
5988                                         a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5989                                         a->AdvSignalPLCI->command = 0;
5990                                         sig_req(a->AdvSignalPLCI, HANGUP, 0);
5991                                         send_req(a->AdvSignalPLCI);
5992                                 }
5993                                 break;
5994                         }
5995                 }
5996                 break;
5997
5998         case RESUME:
5999                 clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
6000                 PUT_WORD(&resume_cau[4], GOOD);
6001                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6002                 break;
6003
6004         case SUSPEND:
6005                 clear_c_ind_mask(plci);
6006
6007                 if (plci->NL.Id && !plci->nl_remove_id) {
6008                         mixer_remove(plci);
6009                         nl_req_ncci(plci, REMOVE, 0);
6010                 }
6011                 if (!plci->sig_remove_id) {
6012                         plci->internal_command = 0;
6013                         sig_req(plci, REMOVE, 0);
6014                 }
6015                 send_req(plci);
6016                 if (!plci->channels) {
6017                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6018                         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6019                 }
6020                 break;
6021
6022         case SUSPEND_REJ:
6023                 break;
6024
6025         case HANGUP:
6026                 plci->hangup_flow_ctrl_timer = 0;
6027                 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6028                 cau = parms[7];
6029                 if (cau) {
6030                         i = _L3_CAUSE | cau[2];
6031                         if (cau[2] == 0) i = 0;
6032                         else if (cau[2] == 8) i = _L1_ERROR;
6033                         else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6034                         else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6035                 }
6036                 else {
6037                         i = _L3_ERROR;
6038                 }
6039
6040                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6041                 {
6042                         for (i = 0; i < max_appl; i++)
6043                         {
6044                                 if (test_c_ind_mask_bit(plci, i))
6045                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6046                         }
6047                 }
6048                 else
6049                 {
6050                         clear_c_ind_mask(plci);
6051                 }
6052                 if (!plci->appl)
6053                 {
6054                         if (plci->State == LISTENING)
6055                         {
6056                                 plci->notifiedcall = 0;
6057                                 a->listen_active--;
6058                         }
6059                         plci->State = INC_DIS_PENDING;
6060                         if (c_ind_mask_empty(plci))
6061                         {
6062                                 plci->State = IDLE;
6063                                 if (plci->NL.Id && !plci->nl_remove_id)
6064                                 {
6065                                         mixer_remove(plci);
6066                                         nl_req_ncci(plci, REMOVE, 0);
6067                                 }
6068                                 if (!plci->sig_remove_id)
6069                                 {
6070                                         plci->internal_command = 0;
6071                                         sig_req(plci, REMOVE, 0);
6072                                 }
6073                                 send_req(plci);
6074                         }
6075                 }
6076                 else
6077                 {
6078                         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6079                         /* result in a second HANGUP! Don't generate another        */
6080                         /* DISCONNECT                                               */
6081                         if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6082                         {
6083                                 if (plci->State == RESUMING)
6084                                 {
6085                                         PUT_WORD(&resume_cau[4], i);
6086                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6087                                 }
6088                                 plci->State = INC_DIS_PENDING;
6089                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6090                         }
6091                 }
6092                 break;
6093
6094         case SSEXT_IND:
6095                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6096                 break;
6097
6098         case VSWITCH_REQ:
6099                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
6100                 break;
6101         case VSWITCH_IND:
6102                 if (plci->relatedPTYPLCI &&
6103                     plci->vswitchstate == 3 &&
6104                     plci->relatedPTYPLCI->vswitchstate == 3 &&
6105                     parms[MAXPARMSIDS - 1][0])
6106                 {
6107                         add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6108                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6109                         send_req(plci->relatedPTYPLCI);
6110                 }
6111                 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6112                 break;
6113
6114         }
6115 }
6116
6117
6118 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6119 {
6120         word i;
6121         byte *ie;
6122         word Info_Number;
6123         byte *Info_Element;
6124         word Info_Mask = 0;
6125
6126         dbug(1, dprintf("SetupInfo"));
6127
6128         for (i = 0; i < MAXPARMSIDS; i++) {
6129                 ie = parms[i];
6130                 Info_Number = 0;
6131                 Info_Element = ie;
6132                 if (ie[0]) {
6133                         switch (i) {
6134                         case 0:
6135                                 dbug(1, dprintf("CPN "));
6136                                 Info_Number = 0x0070;
6137                                 Info_Mask = 0x80;
6138                                 Info_Sent_Flag = true;
6139                                 break;
6140                         case 8:  /* display      */
6141                                 dbug(1, dprintf("display(%d)", i));
6142                                 Info_Number = 0x0028;
6143                                 Info_Mask = 0x04;
6144                                 Info_Sent_Flag = true;
6145                                 break;
6146                         case 16: /* Channel Id */
6147                                 dbug(1, dprintf("CHI"));
6148                                 Info_Number = 0x0018;
6149                                 Info_Mask = 0x100;
6150                                 Info_Sent_Flag = true;
6151                                 mixer_set_bchannel_id(plci, Info_Element);
6152                                 break;
6153                         case 19: /* Redirected Number */
6154                                 dbug(1, dprintf("RDN"));
6155                                 Info_Number = 0x0074;
6156                                 Info_Mask = 0x400;
6157                                 Info_Sent_Flag = true;
6158                                 break;
6159                         case 20: /* Redirected Number extended */
6160                                 dbug(1, dprintf("RDX"));
6161                                 Info_Number = 0x0073;
6162                                 Info_Mask = 0x400;
6163                                 Info_Sent_Flag = true;
6164                                 break;
6165                         case 22: /* Redirecing Number  */
6166                                 dbug(1, dprintf("RIN"));
6167                                 Info_Number = 0x0076;
6168                                 Info_Mask = 0x400;
6169                                 Info_Sent_Flag = true;
6170                                 break;
6171                         default:
6172                                 Info_Number = 0;
6173                                 break;
6174                         }
6175                 }
6176
6177                 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6178                         Info_Number = 0x8000 | 5;
6179                         Info_Mask = 0x10;
6180                         Info_Element = "";
6181                 }
6182
6183                 if (Info_Sent_Flag && Info_Number) {
6184                         if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6185                                 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6186                         }
6187                 }
6188         }
6189 }
6190
6191
6192 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6193 {
6194         word i;
6195         word j;
6196         word k;
6197         byte *ie;
6198         word Info_Number;
6199         byte *Info_Element;
6200         word Info_Mask = 0;
6201         static byte charges[5] = {4, 0, 0, 0, 0};
6202         static byte cause[] = {0x02, 0x80, 0x00};
6203         APPL *appl;
6204
6205         dbug(1, dprintf("InfoParse "));
6206
6207         if (
6208                 !plci->appl
6209                 && !plci->State
6210                 && plci->Sig.Ind != NCR_FACILITY
6211                 )
6212         {
6213                 dbug(1, dprintf("NoParse "));
6214                 return;
6215         }
6216         cause[2] = 0;
6217         for (i = 0; i < MAXPARMSIDS; i++) {
6218                 ie = parms[i];
6219                 Info_Number = 0;
6220                 Info_Element = ie;
6221                 if (ie[0]) {
6222                         switch (i) {
6223                         case 0:
6224                                 dbug(1, dprintf("CPN "));
6225                                 Info_Number = 0x0070;
6226                                 Info_Mask   = 0x80;
6227                                 break;
6228                         case 7: /* ESC_CAU */
6229                                 dbug(1, dprintf("cau(0x%x)", ie[2]));
6230                                 Info_Number = 0x0008;
6231                                 Info_Mask = 0x00;
6232                                 cause[2] = ie[2];
6233                                 Info_Element = NULL;
6234                                 break;
6235                         case 8:  /* display      */
6236                                 dbug(1, dprintf("display(%d)", i));
6237                                 Info_Number = 0x0028;
6238                                 Info_Mask = 0x04;
6239                                 break;
6240                         case 9:  /* Date display */
6241                                 dbug(1, dprintf("date(%d)", i));
6242                                 Info_Number = 0x0029;
6243                                 Info_Mask = 0x02;
6244                                 break;
6245                         case 10: /* charges */
6246                                 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6247                                 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6248                                 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6249                                 Info_Number = 0x4000;
6250                                 Info_Mask = 0x40;
6251                                 Info_Element = charges;
6252                                 break;
6253                         case 11: /* user user info */
6254                                 dbug(1, dprintf("uui"));
6255                                 Info_Number = 0x007E;
6256                                 Info_Mask = 0x08;
6257                                 break;
6258                         case 12: /* congestion receiver ready */
6259                                 dbug(1, dprintf("clRDY"));
6260                                 Info_Number = 0x00B0;
6261                                 Info_Mask = 0x08;
6262                                 Info_Element = "";
6263                                 break;
6264                         case 13: /* congestion receiver not ready */
6265                                 dbug(1, dprintf("clNRDY"));
6266                                 Info_Number = 0x00BF;
6267                                 Info_Mask = 0x08;
6268                                 Info_Element = "";
6269                                 break;
6270                         case 15: /* Keypad Facility */
6271                                 dbug(1, dprintf("KEY"));
6272                                 Info_Number = 0x002C;
6273                                 Info_Mask = 0x20;
6274                                 break;
6275                         case 16: /* Channel Id */
6276                                 dbug(1, dprintf("CHI"));
6277                                 Info_Number = 0x0018;
6278                                 Info_Mask = 0x100;
6279                                 mixer_set_bchannel_id(plci, Info_Element);
6280                                 break;
6281                         case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6282                                 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6283                                 if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6284                                 Info_Number = 0x0008;
6285                                 Info_Mask = 0x01;
6286                                 if (cause[2] != ie[2]) Info_Element = cause;
6287                                 break;
6288                         case 19: /* Redirected Number */
6289                                 dbug(1, dprintf("RDN"));
6290                                 Info_Number = 0x0074;
6291                                 Info_Mask = 0x400;
6292                                 break;
6293                         case 22: /* Redirecing Number  */
6294                                 dbug(1, dprintf("RIN"));
6295                                 Info_Number = 0x0076;
6296                                 Info_Mask = 0x400;
6297                                 break;
6298                         case 23: /* Notification Indicator  */
6299                                 dbug(1, dprintf("NI"));
6300                                 Info_Number = (word)NI;
6301                                 Info_Mask = 0x210;
6302                                 break;
6303                         case 26: /* Call State  */
6304                                 dbug(1, dprintf("CST"));
6305                                 Info_Number = (word)CST;
6306                                 Info_Mask = 0x01; /* do with cause i.e. for now */
6307                                 break;
6308                         case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6309                                 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6310                                 Info_Number = 0x8000 | ie[3];
6311                                 if (iesent) Info_Mask = 0xffff;
6312                                 else  Info_Mask = 0x10;
6313                                 Info_Element = "";
6314                                 break;
6315                         default:
6316                                 Info_Number  = 0;
6317                                 Info_Mask    = 0;
6318                                 Info_Element = "";
6319                                 break;
6320                         }
6321                 }
6322
6323                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6324                 {
6325                         for (j = 0; j < max_appl; j++)
6326                         {
6327                                 appl = &application[j];
6328                                 if (Info_Number
6329                                     && appl->Id
6330                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6331                                 {
6332                                         dbug(1, dprintf("NCR_Ind"));
6333                                         iesent = true;
6334                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6335                                 }
6336                         }
6337                 }
6338                 else if (!plci->appl)
6339                 { /* overlap receiving broadcast */
6340                         if (Info_Number == CPN
6341                             || Info_Number == KEY
6342                             || Info_Number == NI
6343                             || Info_Number == DSP
6344                             || Info_Number == UUI)
6345                         {
6346                                 for (j = 0; j < max_appl; j++)
6347                                 {
6348                                         if (test_c_ind_mask_bit(plci, j))
6349                                         {
6350                                                 dbug(1, dprintf("Ovl_Ind"));
6351                                                 iesent = true;
6352                                                 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6353                                         }
6354                                 }
6355                         }
6356                 }               /* all other signalling states */
6357                 else if (Info_Number
6358                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6359                 {
6360                         dbug(1, dprintf("Std_Ind"));
6361                         iesent = true;
6362                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6363                 }
6364         }
6365 }
6366
6367
6368 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6369                         dword info_mask, byte setupParse)
6370 {
6371         word i;
6372         word j;
6373         byte *ie;
6374         word Info_Number;
6375         byte *Info_Element;
6376         APPL *appl;
6377         word Info_Mask = 0;
6378         byte iesent = 0;
6379
6380         if (
6381                 !plci->appl
6382                 && !plci->State
6383                 && plci->Sig.Ind != NCR_FACILITY
6384                 && !setupParse
6385                 )
6386         {
6387                 dbug(1, dprintf("NoM-IEParse "));
6388                 return 0;
6389         }
6390         dbug(1, dprintf("M-IEParse "));
6391
6392         for (i = 0; i < MAX_MULTI_IE; i++)
6393         {
6394                 ie = parms[i];
6395                 Info_Number = 0;
6396                 Info_Element = ie;
6397                 if (ie[0])
6398                 {
6399                         dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6400                         Info_Number = (word)ie_type;
6401                         Info_Mask = (word)info_mask;
6402                 }
6403
6404                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6405                 {
6406                         for (j = 0; j < max_appl; j++)
6407                         {
6408                                 appl = &application[j];
6409                                 if (Info_Number
6410                                     && appl->Id
6411                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6412                                 {
6413                                         iesent = true;
6414                                         dbug(1, dprintf("Mlt_NCR_Ind"));
6415                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6416                                 }
6417                         }
6418                 }
6419                 else if (!plci->appl && Info_Number)
6420                 {                                        /* overlap receiving broadcast */
6421                         for (j = 0; j < max_appl; j++)
6422                         {
6423                                 if (test_c_ind_mask_bit(plci, j))
6424                                 {
6425                                         iesent = true;
6426                                         dbug(1, dprintf("Mlt_Ovl_Ind"));
6427                                         sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6428                                 }
6429                         }
6430                 }                                        /* all other signalling states */
6431                 else if (Info_Number
6432                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6433                 {
6434                         iesent = true;
6435                         dbug(1, dprintf("Mlt_Std_Ind"));
6436                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6437                 }
6438         }
6439         return iesent;
6440 }
6441
6442 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6443 {
6444         word i;
6445         /* Format of multi_ssext_parms[i][]:
6446            0 byte length
6447            1 byte SSEXTIE
6448            2 byte SSEXT_REQ/SSEXT_IND
6449            3 byte length
6450            4 word SSExtCommand
6451            6... Params
6452         */
6453         if (
6454                 plci
6455                 && plci->State
6456                 && plci->Sig.Ind != NCR_FACILITY
6457                 )
6458                 for (i = 0; i < MAX_MULTI_IE; i++)
6459                 {
6460                         if (parms[i][0] < 6) continue;
6461                         if (parms[i][2] == SSEXT_REQ) continue;
6462
6463                         if (appl)
6464                         {
6465                                 parms[i][0] = 0; /* kill it */
6466                                 sendf(appl, _MANUFACTURER_I,
6467                                       Id,
6468                                       0,
6469                                       "dwS",
6470                                       _DI_MANU_ID,
6471                                       _DI_SSEXT_CTRL,
6472                                       &parms[i][3]);
6473                         }
6474                         else if (plci->appl)
6475                         {
6476                                 parms[i][0] = 0; /* kill it */
6477                                 sendf(plci->appl, _MANUFACTURER_I,
6478                                       Id,
6479                                       0,
6480                                       "dwS",
6481                                       _DI_MANU_ID,
6482                                       _DI_SSEXT_CTRL,
6483                                       &parms[i][3]);
6484                         }
6485                 }
6486 };
6487
6488 static void nl_ind(PLCI *plci)
6489 {
6490         byte ch;
6491         word ncci;
6492         dword Id;
6493         DIVA_CAPI_ADAPTER *a;
6494         word NCCIcode;
6495         APPL *APPLptr;
6496         word count;
6497         word Num;
6498         word i, ncpi_state;
6499         byte len, ncci_state;
6500         word msg;
6501         word info = 0;
6502         word fax_feature_bits;
6503         byte fax_send_edata_ack;
6504         static byte v120_header_buffer[2 + 3];
6505         static word fax_info[] = {
6506                 0,                     /* T30_SUCCESS                        */
6507                 _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6508                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6509                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6510                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6511                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6512                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6513                 _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6514                 _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6515                 _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6516                 _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6517                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6518                 _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6519                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6520                 _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6521                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6522                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6523                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6524                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6525                 _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6526                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6527                 _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6528                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6529                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6530                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6531                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6532                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6533                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6534                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6535                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6536                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6537                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6538                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6539                 0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6540                 0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6541                 0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6542                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6543                 _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6544                 _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6545                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6546                 _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6547                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6548                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6549                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6550                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6551                 _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6552                 _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6553         };
6554
6555         byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6556
6557
6558         static word rtp_info[] = {
6559                 GOOD,                  /* RTP_SUCCESS                       */
6560                 0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6561         };
6562
6563         static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6564                 {
6565                         0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6566                         0x00000000, 0x00000000, 0x00000000, 0x00000000
6567                 };
6568
6569         ch = plci->NL.IndCh;
6570         a = plci->adapter;
6571         ncci = a->ch_ncci[ch];
6572         Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6573         if (plci->tel) Id |= EXT_CONTROLLER;
6574         APPLptr = plci->appl;
6575         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",
6576                         plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6577
6578         /* in the case if no connect_active_Ind was sent to the appl we wait for */
6579
6580         if (plci->nl_remove_id)
6581         {
6582                 plci->NL.RNR = 2; /* discard */
6583                 dbug(1, dprintf("NL discard while remove pending"));
6584                 return;
6585         }
6586         if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6587         {
6588                 if (plci->State == INC_DIS_PENDING
6589                     || plci->State == OUTG_DIS_PENDING
6590                     || plci->State == IDLE)
6591                 {
6592                         plci->NL.RNR = 2; /* discard */
6593                         dbug(1, dprintf("discard n_connect"));
6594                         return;
6595                 }
6596                 if (plci->State < INC_ACT_PENDING)
6597                 {
6598                         plci->NL.RNR = 1; /* flow control */
6599                         channel_x_off(plci, ch, N_XON_CONNECT_IND);
6600                         return;
6601                 }
6602         }
6603
6604         if (!APPLptr)                         /* no application or invalid data */
6605         {                                    /* while reloading the DSP        */
6606                 dbug(1, dprintf("discard1"));
6607                 plci->NL.RNR = 2;
6608                 return;
6609         }
6610
6611         if (((plci->NL.Ind & 0x0f) == N_UDATA)
6612             && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6613                 || (plci->B2_prot == 7)
6614                 || (plci->B3_prot == 7)))
6615         {
6616                 plci->ncpi_buffer[0] = 0;
6617
6618                 ncpi_state = plci->ncpi_state;
6619                 if (plci->NL.complete == 1)
6620                 {
6621                         byte *data = &plci->NL.RBuffer->P[0];
6622
6623                         if ((plci->NL.RBuffer->length >= 12)
6624                             && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6625                                 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6626                         {
6627                                 word conn_opt, ncpi_opt = 0x00;
6628 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6629
6630                                 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6631                                         plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6632                                 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6633                                         plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6634
6635                                 data++;    /* indication code */
6636                                 data += 2; /* timestamp */
6637                                 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6638                                         ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6639                                 data++;    /* connected norm */
6640                                 conn_opt = GET_WORD(data);
6641                                 data += 2; /* connected options */
6642
6643                                 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6644
6645                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6646                                 {
6647                                         ncpi_opt |= MDM_NCPI_ECM_V42;
6648                                 }
6649                                 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6650                                 {
6651                                         ncpi_opt |= MDM_NCPI_ECM_MNP;
6652                                 }
6653                                 else
6654                                 {
6655                                         ncpi_opt |= MDM_NCPI_TRANSPARENT;
6656                                 }
6657                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6658                                 {
6659                                         ncpi_opt |= MDM_NCPI_COMPRESSED;
6660                                 }
6661                                 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6662                                 plci->ncpi_buffer[0] = 4;
6663
6664                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6665                         }
6666                 }
6667                 if (plci->B3_prot == 7)
6668                 {
6669                         if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6670                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6671                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6672                         {
6673                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6674                                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6675                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6676                         }
6677                 }
6678
6679                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6680                       & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6681                     || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6682                     || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6683
6684                 {
6685                         plci->NL.RNR = 2;
6686                         return;
6687                 }
6688         }
6689
6690         if (plci->NL.complete == 2)
6691         {
6692                 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6693                     && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6694                 {
6695                         switch (plci->RData[0].P[0])
6696                         {
6697
6698                         case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6699                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6700                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6701                                 break;
6702                         case DTMF_UDATA_INDICATION_ANSWER_TONE:
6703                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6705                                 break;
6706                         case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6707                                 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6708                                 break;
6709                         case DTMF_UDATA_INDICATION_DIGITS_SENT:
6710                                 dtmf_confirmation(Id, plci);
6711                                 break;
6712
6713
6714                         case UDATA_INDICATION_MIXER_TAP_DATA:
6715                                 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6716                                 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6717                                 if (i != 0)
6718                                 {
6719                                         dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6720                                         dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6721                                 }
6722                                 break;
6723
6724
6725                         case UDATA_INDICATION_MIXER_COEFS_SET:
6726                                 mixer_indication_coefs_set(Id, plci);
6727                                 break;
6728                         case UDATA_INDICATION_XCONNECT_FROM:
6729                                 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6730                                 break;
6731                         case UDATA_INDICATION_XCONNECT_TO:
6732                                 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6733                                 break;
6734
6735
6736                         case LEC_UDATA_INDICATION_DISABLE_DETECT:
6737                                 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6738                                 break;
6739
6740
6741
6742                         default:
6743                                 break;
6744                         }
6745                 }
6746                 else
6747                 {
6748                         if ((plci->RData[0].PLength != 0)
6749                             && ((plci->B2_prot == B2_V120_ASYNC)
6750                                 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6751                                 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6752                         {
6753
6754                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6755                                       "dwww",
6756                                       plci->RData[1].P,
6757                                       (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6758                                       plci->RNum,
6759                                       plci->RFlags);
6760
6761                         }
6762                         else
6763                         {
6764
6765                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6766                                       "dwww",
6767                                       plci->RData[0].P,
6768                                       plci->RData[0].PLength,
6769                                       plci->RNum,
6770                                       plci->RFlags);
6771
6772                         }
6773                 }
6774                 return;
6775         }
6776
6777         fax_feature_bits = 0;
6778         if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6779             (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6780             (plci->NL.Ind & 0x0f) == N_DISC ||
6781             (plci->NL.Ind & 0x0f) == N_EDATA ||
6782             (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6783         {
6784                 info = 0;
6785                 plci->ncpi_buffer[0] = 0;
6786                 switch (plci->B3_prot) {
6787                 case  0: /*XPARENT*/
6788                 case  1: /*T.90 NL*/
6789                         break;    /* no network control protocol info - jfr */
6790                 case  2: /*ISO8202*/
6791                 case  3: /*X25 DCE*/
6792                         for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6793                         plci->ncpi_buffer[0] = (byte)(i + 3);
6794                         plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6795                         plci->ncpi_buffer[2] = 0;
6796                         plci->ncpi_buffer[3] = 0;
6797                         break;
6798                 case  4: /*T.30 - FAX*/
6799                 case  5: /*T.30 - FAX*/
6800                         if (plci->NL.RLength >= sizeof(T30_INFO))
6801                         {
6802                                 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6803                                 len = 9;
6804                                 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6805                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6806                                 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6807                                 if (plci->B3_prot == 5)
6808                                 {
6809                                         if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6810                                                 i |= 0x8000; /* This is not an ECM connection */
6811                                         if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6812                                                 i |= 0x4000; /* This is a connection with MMR compression */
6813                                         if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6814                                                 i |= 0x2000; /* This is a connection with MR compression */
6815                                         if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6816                                                 i |= 0x0004; /* More documents */
6817                                         if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6818                                                 i |= 0x0002; /* Fax-polling indication */
6819                                 }
6820                                 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6821                                 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6822                                 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6823                                 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6824                                 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6825                                 plci->ncpi_buffer[len] = 0;
6826                                 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6827                                 {
6828                                         plci->ncpi_buffer[len] = 20;
6829                                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6830                                                 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6831                                 }
6832                                 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6833                                 {
6834                                         if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6835                                                 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6836                                         else
6837                                                 info = _FAX_PROTOCOL_ERROR;
6838                                 }
6839
6840                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6841                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6842                                 {
6843                                         i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6844                                         while (i < plci->NL.RBuffer->length)
6845                                                 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6846                                 }
6847
6848                                 plci->ncpi_buffer[0] = len;
6849                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6850                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6851
6852                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6853                                 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6854                                     || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6855                                         && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6856                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6857                                         && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6858                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6859                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6860                                 {
6861                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6862                                 }
6863                                 if (((plci->NL.Ind & 0x0f) == N_DISC)
6864                                     || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6865                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6866                                         && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6867                                 {
6868                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6869                                 }
6870                         }
6871                         break;
6872
6873                 case B3_RTP:
6874                         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6875                         {
6876                                 if (plci->NL.RLength != 0)
6877                                 {
6878                                         info = rtp_info[plci->NL.RBuffer->P[0]];
6879                                         plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6880                                         for (i = 1; i < plci->NL.RLength; i++)
6881                                                 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6882                                 }
6883                         }
6884                         break;
6885
6886                 }
6887                 plci->NL.RNR = 2;
6888         }
6889         switch (plci->NL.Ind & 0x0f) {
6890         case N_EDATA:
6891                 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6892                 {
6893                         dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6894                                         ((T30_INFO *)plci->NL.RBuffer->P)->code));
6895                         fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6896
6897                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6898                             && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6899                             && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6900                             && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6901                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6902                             && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6903                         {
6904                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6905                                 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6906                                       (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6907                                 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6908                                 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6909                                         fax_send_edata_ack = false;
6910                         }
6911
6912                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6913                         {
6914                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6915                                 {
6916                                 case EDATA_T30_DIS:
6917                                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6918                                             && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6919                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6920                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6921                                         {
6922                                                 a->ncci_state[ncci] = INC_ACT_PENDING;
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_TRAIN_OK:
6932                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6933                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6934                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6935                                         {
6936                                                 if (plci->B3_prot == 4)
6937                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6938                                                 else
6939                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6940                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6941                                         }
6942                                         break;
6943
6944                                 case EDATA_T30_EOP_CAPI:
6945                                         if (a->ncci_state[ncci] == CONNECTED)
6946                                         {
6947                                                 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6948                                                 a->ncci_state[ncci] = INC_DIS_PENDING;
6949                                                 plci->ncpi_state = 0;
6950                                                 fax_send_edata_ack = false;
6951                                         }
6952                                         break;
6953                                 }
6954                         }
6955                         else
6956                         {
6957                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6958                                 {
6959                                 case EDATA_T30_TRAIN_OK:
6960                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6961                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6962                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6963                                         {
6964                                                 if (plci->B3_prot == 4)
6965                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6966                                                 else
6967                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6968                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6969                                         }
6970                                         break;
6971                                 }
6972                         }
6973                         if (fax_send_edata_ack)
6974                         {
6975                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6976                                 plci->fax_edata_ack_length = 1;
6977                                 start_internal_command(Id, plci, fax_edata_ack_command);
6978                         }
6979                 }
6980                 else
6981                 {
6982                         dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6983                 }
6984                 break;
6985         case N_CONNECT:
6986                 if (!a->ch_ncci[ch])
6987                 {
6988                         ncci = get_ncci(plci, ch, 0);
6989                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
6990                 }
6991                 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6992                                 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6993
6994                 msg = _CONNECT_B3_I;
6995                 if (a->ncci_state[ncci] == IDLE)
6996                         plci->channels++;
6997                 else if (plci->B3_prot == 1)
6998                         msg = _CONNECT_B3_T90_ACTIVE_I;
6999
7000                 a->ncci_state[ncci] = INC_CON_PENDING;
7001                 if (plci->B3_prot == 4)
7002                         sendf(plci->appl, msg, Id, 0, "s", "");
7003                 else
7004                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7005                 break;
7006         case N_CONNECT_ACK:
7007                 dbug(1, dprintf("N_connect_Ack"));
7008                 if (plci->internal_command_queue[0]
7009                     && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7010                         || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7011                         || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7012                 {
7013                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
7014                         if (!plci->internal_command)
7015                                 next_internal_command(Id, plci);
7016                         break;
7017                 }
7018                 msg = _CONNECT_B3_ACTIVE_I;
7019                 if (plci->B3_prot == 1)
7020                 {
7021                         if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7022                                 msg = _CONNECT_B3_T90_ACTIVE_I;
7023                         a->ncci_state[ncci] = INC_ACT_PENDING;
7024                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7025                 }
7026                 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7027                 {
7028                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7029                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7030                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7031                         {
7032                                 a->ncci_state[ncci] = INC_ACT_PENDING;
7033                                 if (plci->B3_prot == 4)
7034                                         sendf(plci->appl, msg, Id, 0, "s", "");
7035                                 else
7036                                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7037                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7038                         }
7039                 }
7040                 else
7041                 {
7042                         a->ncci_state[ncci] = INC_ACT_PENDING;
7043                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7044                 }
7045                 if (plci->adjust_b_restore)
7046                 {
7047                         plci->adjust_b_restore = false;
7048                         start_internal_command(Id, plci, adjust_b_restore);
7049                 }
7050                 break;
7051         case N_DISC:
7052         case N_DISC_ACK:
7053                 if (plci->internal_command_queue[0]
7054                     && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7055                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7056                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7057                 {
7058                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
7059                         if (!plci->internal_command)
7060                                 next_internal_command(Id, plci);
7061                 }
7062                 ncci_state = a->ncci_state[ncci];
7063                 ncci_remove(plci, ncci, false);
7064
7065                 /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7066                 /* channel, so we cannot store the state in ncci_state! The */
7067                 /* information which channel we received a N_DISC is thus   */
7068                 /* stored in the inc_dis_ncci_table buffer.                 */
7069                 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7070                 plci->inc_dis_ncci_table[i] = (byte) ncci;
7071
7072                 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7073                 if (!plci->channels
7074                     && (plci->B1_resource == 16)
7075                     && (plci->State <= CONNECTED))
7076                 {
7077                         len = 9;
7078                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7079                         PUT_WORD(&plci->ncpi_buffer[1], i);
7080                         PUT_WORD(&plci->ncpi_buffer[3], 0);
7081                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7082                         PUT_WORD(&plci->ncpi_buffer[5], i);
7083                         PUT_WORD(&plci->ncpi_buffer[7], 0);
7084                         plci->ncpi_buffer[len] = 0;
7085                         plci->ncpi_buffer[0] = len;
7086                         if (plci->B3_prot == 4)
7087                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7088                         else
7089                         {
7090
7091                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7092                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7093                                 {
7094                                         plci->ncpi_buffer[++len] = 0;
7095                                         plci->ncpi_buffer[++len] = 0;
7096                                         plci->ncpi_buffer[++len] = 0;
7097                                         plci->ncpi_buffer[0] = len;
7098                                 }
7099
7100                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7101                         }
7102                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7103                         plci->ncpi_state = 0;
7104                         sig_req(plci, HANGUP, 0);
7105                         send_req(plci);
7106                         plci->State = OUTG_DIS_PENDING;
7107                         /* disc here */
7108                 }
7109                 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7110                          && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7111                          && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7112                 {
7113                         if (ncci_state == IDLE)
7114                         {
7115                                 if (plci->channels)
7116                                         plci->channels--;
7117                                 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7118                                         if (plci->State == SUSPENDING) {
7119                                                 sendf(plci->appl,
7120                                                       _FACILITY_I,
7121                                                       Id & 0xffffL,
7122                                                       0,
7123                                                       "ws", (word)3, "\x03\x04\x00\x00");
7124                                                 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7125                                         }
7126                                         plci_remove(plci);
7127                                         plci->State = IDLE;
7128                                 }
7129                         }
7130                 }
7131                 else if (plci->channels)
7132                 {
7133                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7134                         plci->ncpi_state = 0;
7135                         if ((ncci_state == OUTG_REJ_PENDING)
7136                             && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7137                         {
7138                                 sig_req(plci, HANGUP, 0);
7139                                 send_req(plci);
7140                                 plci->State = OUTG_DIS_PENDING;
7141                         }
7142                 }
7143                 break;
7144         case N_RESET:
7145                 a->ncci_state[ncci] = INC_RES_PENDING;
7146                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7147                 break;
7148         case N_RESET_ACK:
7149                 a->ncci_state[ncci] = CONNECTED;
7150                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7151                 break;
7152
7153         case N_UDATA:
7154                 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7155                 {
7156                         plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7157                         plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7158                         plci->NL.R = plci->RData;
7159                         plci->NL.RNum = 1;
7160                         return;
7161                 }
7162         case N_BDATA:
7163         case N_DATA:
7164                 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7165                     || (a->ncci_state[ncci] == IDLE)
7166                     || (a->ncci_state[ncci] == INC_DIS_PENDING))
7167                 {
7168                         plci->NL.RNR = 2;
7169                         break;
7170                 }
7171                 if ((a->ncci_state[ncci] != CONNECTED)
7172                     && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7173                     && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7174                 {
7175                         dbug(1, dprintf("flow control"));
7176                         plci->NL.RNR = 1; /* flow control  */
7177                         channel_x_off(plci, ch, 0);
7178                         break;
7179                 }
7180
7181                 NCCIcode = ncci | (((word)a->Id) << 8);
7182
7183                 /* count all buffers within the Application pool    */
7184                 /* belonging to the same NCCI. If this is below the */
7185                 /* number of buffers available per NCCI we accept   */
7186                 /* this packet, otherwise we reject it              */
7187                 count = 0;
7188                 Num = 0xffff;
7189                 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7190                         if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7191                         if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7192                 }
7193
7194                 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7195                 {
7196                         dbug(3, dprintf("Flow-Control"));
7197                         plci->NL.RNR = 1;
7198                         if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7199                             (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7200                         {
7201                                 plci->NL.RNR = 2;
7202                                 dbug(3, dprintf("DiscardData"));
7203                         } else {
7204                                 channel_x_off(plci, ch, 0);
7205                         }
7206                         break;
7207                 }
7208                 else
7209                 {
7210                         APPLptr->NCCIDataFlowCtrlTimer = 0;
7211                 }
7212
7213                 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7214                 if (!plci->RData[0].P) {
7215                         plci->NL.RNR = 1;
7216                         channel_x_off(plci, ch, 0);
7217                         break;
7218                 }
7219
7220                 APPLptr->DataNCCI[Num] = NCCIcode;
7221                 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7222                 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7223
7224                 plci->RNum = Num;
7225                 plci->RFlags = plci->NL.Ind >> 4;
7226                 plci->RData[0].PLength = APPLptr->MaxDataLength;
7227                 plci->NL.R = plci->RData;
7228                 if ((plci->NL.RLength != 0)
7229                     && ((plci->B2_prot == B2_V120_ASYNC)
7230                         || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7231                         || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7232                 {
7233                         plci->RData[1].P = plci->RData[0].P;
7234                         plci->RData[1].PLength = plci->RData[0].PLength;
7235                         plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7236                         if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7237                                 plci->RData[0].PLength = 1;
7238                         else
7239                                 plci->RData[0].PLength = 2;
7240                         if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7241                                 plci->RFlags |= 0x0010;
7242                         if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7243                                 plci->RFlags |= 0x8000;
7244                         plci->NL.RNum = 2;
7245                 }
7246                 else
7247                 {
7248                         if ((plci->NL.Ind & 0x0f) == N_UDATA)
7249                                 plci->RFlags |= 0x0010;
7250
7251                         else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7252                                 plci->RFlags |= 0x0001;
7253
7254                         plci->NL.RNum = 1;
7255                 }
7256                 break;
7257         case N_DATA_ACK:
7258                 data_ack(plci, ch);
7259                 break;
7260         default:
7261                 plci->NL.RNR = 2;
7262                 break;
7263         }
7264 }
7265
7266 /*------------------------------------------------------------------*/
7267 /* find a free PLCI */
7268 /*------------------------------------------------------------------*/
7269
7270 static word get_plci(DIVA_CAPI_ADAPTER *a)
7271 {
7272         word i, j;
7273         PLCI *plci;
7274
7275         dump_plcis(a);
7276         for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7277         if (i == a->max_plci) {
7278                 dbug(1, dprintf("get_plci: out of PLCIs"));
7279                 return 0;
7280         }
7281         plci = &a->plci[i];
7282         plci->Id = (byte)(i + 1);
7283
7284         plci->Sig.Id = 0;
7285         plci->NL.Id = 0;
7286         plci->sig_req = 0;
7287         plci->nl_req = 0;
7288
7289         plci->appl = NULL;
7290         plci->relatedPTYPLCI = NULL;
7291         plci->State = IDLE;
7292         plci->SuppState = IDLE;
7293         plci->channels = 0;
7294         plci->tel = 0;
7295         plci->B1_resource = 0;
7296         plci->B2_prot = 0;
7297         plci->B3_prot = 0;
7298
7299         plci->command = 0;
7300         plci->m_command = 0;
7301         init_internal_command_queue(plci);
7302         plci->number = 0;
7303         plci->req_in_start = 0;
7304         plci->req_in = 0;
7305         plci->req_out = 0;
7306         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7307         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7308         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7309
7310         plci->data_sent = false;
7311         plci->send_disc = 0;
7312         plci->sig_global_req = 0;
7313         plci->sig_remove_id = 0;
7314         plci->nl_global_req = 0;
7315         plci->nl_remove_id = 0;
7316         plci->adv_nl = 0;
7317         plci->manufacturer = false;
7318         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7319         plci->spoofed_msg = 0;
7320         plci->ptyState = 0;
7321         plci->cr_enquiry = false;
7322         plci->hangup_flow_ctrl_timer = 0;
7323
7324         plci->ncci_ring_list = 0;
7325         for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7326         clear_c_ind_mask(plci);
7327         set_group_ind_mask(plci);
7328         plci->fax_connect_info_length = 0;
7329         plci->nsf_control_bits = 0;
7330         plci->ncpi_state = 0x00;
7331         plci->ncpi_buffer[0] = 0;
7332
7333         plci->requested_options_conn = 0;
7334         plci->requested_options = 0;
7335         plci->notifiedcall = 0;
7336         plci->vswitchstate = 0;
7337         plci->vsprot = 0;
7338         plci->vsprotdialect = 0;
7339         init_b1_config(plci);
7340         dbug(1, dprintf("get_plci(%x)", plci->Id));
7341         return i + 1;
7342 }
7343
7344 /*------------------------------------------------------------------*/
7345 /* put a parameter in the parameter buffer                          */
7346 /*------------------------------------------------------------------*/
7347
7348 static void add_p(PLCI *plci, byte code, byte *p)
7349 {
7350         word p_length;
7351
7352         p_length = 0;
7353         if (p) p_length = p[0];
7354         add_ie(plci, code, p, p_length);
7355 }
7356
7357 /*------------------------------------------------------------------*/
7358 /* put a structure in the parameter buffer                          */
7359 /*------------------------------------------------------------------*/
7360 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7361 {
7362         if (p) add_ie(plci, code, p->info, (word)p->length);
7363 }
7364
7365 /*------------------------------------------------------------------*/
7366 /* put multiple structures in the parameter buffer                  */
7367 /*------------------------------------------------------------------*/
7368 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7369 {
7370         byte i;
7371
7372         if (p) {
7373                 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7374                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7375                         dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7376                         add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7377                 }
7378         }
7379 }
7380
7381 /*------------------------------------------------------------------*/
7382 /* return the channel number sent by the application in a esc_chi   */
7383 /*------------------------------------------------------------------*/
7384 static byte getChannel(API_PARSE *p)
7385 {
7386         byte i;
7387
7388         if (p) {
7389                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7390                         if (p->info[i] == 2) {
7391                                 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7392                         }
7393                 }
7394         }
7395         return 0;
7396 }
7397
7398
7399 /*------------------------------------------------------------------*/
7400 /* put an information element in the parameter buffer               */
7401 /*------------------------------------------------------------------*/
7402
7403 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7404 {
7405         word i;
7406
7407         if (!(code & 0x80) && !p_length) return;
7408
7409         if (plci->req_in == plci->req_in_start) {
7410                 plci->req_in += 2;
7411         }
7412         else {
7413                 plci->req_in--;
7414         }
7415         plci->RBuffer[plci->req_in++] = code;
7416
7417         if (p) {
7418                 plci->RBuffer[plci->req_in++] = (byte)p_length;
7419                 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7420         }
7421
7422         plci->RBuffer[plci->req_in++] = 0;
7423 }
7424
7425 /*------------------------------------------------------------------*/
7426 /* put a unstructured data into the buffer                          */
7427 /*------------------------------------------------------------------*/
7428
7429 static void add_d(PLCI *plci, word length, byte *p)
7430 {
7431         word i;
7432
7433         if (plci->req_in == plci->req_in_start) {
7434                 plci->req_in += 2;
7435         }
7436         else {
7437                 plci->req_in--;
7438         }
7439         for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7440 }
7441
7442 /*------------------------------------------------------------------*/
7443 /* put parameters from the Additional Info parameter in the         */
7444 /* parameter buffer                                                 */
7445 /*------------------------------------------------------------------*/
7446
7447 static void add_ai(PLCI *plci, API_PARSE *ai)
7448 {
7449         word i;
7450         API_PARSE ai_parms[5];
7451
7452         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7453
7454         if (!ai->length)
7455                 return;
7456         if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7457                 return;
7458
7459         add_s(plci, KEY, &ai_parms[1]);
7460         add_s(plci, UUI, &ai_parms[2]);
7461         add_ss(plci, FTY, &ai_parms[3]);
7462 }
7463
7464 /*------------------------------------------------------------------*/
7465 /* put parameter for b1 protocol in the parameter buffer            */
7466 /*------------------------------------------------------------------*/
7467
7468 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7469                    word b1_facilities)
7470 {
7471         API_PARSE bp_parms[8];
7472         API_PARSE mdm_cfg[9];
7473         API_PARSE global_config[2];
7474         byte cai[256];
7475         byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7476         byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7477         word i;
7478
7479         API_PARSE mdm_cfg_v18[4];
7480         word j, n, w;
7481         dword d;
7482
7483
7484         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7485         for (i = 0; i < 2; i++) global_config[i].length = 0;
7486
7487         dbug(1, dprintf("add_b1"));
7488         api_save_msg(bp, "s", &plci->B_protocol);
7489
7490         if (b_channel_info == 2) {
7491                 plci->B1_resource = 0;
7492                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7493                 add_p(plci, CAI, "\x01\x00");
7494                 dbug(1, dprintf("Cai=1,0 (no resource)"));
7495                 return 0;
7496         }
7497
7498         if (plci->tel == CODEC_PERMANENT) return 0;
7499         else if (plci->tel == CODEC) {
7500                 plci->B1_resource = 1;
7501                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7502                 add_p(plci, CAI, "\x01\x01");
7503                 dbug(1, dprintf("Cai=1,1 (Codec)"));
7504                 return 0;
7505         }
7506         else if (plci->tel == ADV_VOICE) {
7507                 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7508                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7509                 voice_cai[1] = plci->B1_resource;
7510                 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7511                 add_p(plci, CAI, voice_cai);
7512                 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7513                 return 0;
7514         }
7515         plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7516         if (plci->call_dir & CALL_DIR_OUT)
7517                 plci->call_dir |= CALL_DIR_ORIGINATE;
7518         else if (plci->call_dir & CALL_DIR_IN)
7519                 plci->call_dir |= CALL_DIR_ANSWER;
7520
7521         if (!bp->length) {
7522                 plci->B1_resource = 0x5;
7523                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7524                 add_p(plci, CAI, "\x01\x05");
7525                 return 0;
7526         }
7527
7528         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7529         if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7530         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7531         {
7532                 bp_parms[6].length = 0;
7533                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7534                 {
7535                         dbug(1, dprintf("b-form.!"));
7536                         return _WRONG_MESSAGE_FORMAT;
7537                 }
7538         }
7539         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7540         {
7541                 dbug(1, dprintf("b-form.!"));
7542                 return _WRONG_MESSAGE_FORMAT;
7543         }
7544
7545         if (bp_parms[6].length)
7546         {
7547                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7548                 {
7549                         return _WRONG_MESSAGE_FORMAT;
7550                 }
7551                 switch (GET_WORD(global_config[0].info))
7552                 {
7553                 case 1:
7554                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7555                         break;
7556                 case 2:
7557                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7558                         break;
7559                 }
7560         }
7561         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7562
7563
7564         if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7565             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7566         {
7567                 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7568                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7569                 cai[1] = plci->B1_resource;
7570                 cai[2] = 0;
7571                 cai[3] = 0;
7572                 cai[4] = 0;
7573                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7574                 for (i = 0; i < bp_parms[3].length; i++)
7575                         cai[7 + i] = bp_parms[3].info[1 + i];
7576                 cai[0] = 6 + bp_parms[3].length;
7577                 add_p(plci, CAI, cai);
7578                 return 0;
7579         }
7580
7581
7582         if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7583             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7584         {
7585                 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7586                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587                 cai[1] = plci->B1_resource;
7588                 cai[2] = 0;
7589                 cai[3] = 0;
7590                 cai[4] = 0;
7591                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7592                 cai[0] = 6;
7593                 add_p(plci, CAI, cai);
7594                 return 0;
7595         }
7596
7597
7598         if ((GET_WORD(bp_parms[0].info) >= 32)
7599             || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7600                 && ((GET_WORD(bp_parms[0].info) != 3)
7601                     || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7602                     || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7603         {
7604                 return _B1_NOT_SUPPORTED;
7605         }
7606         plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7607                                               (word)(b1_facilities & ~B1_FACILITY_VOICE));
7608         adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7609         cai[0] = 6;
7610         cai[1] = plci->B1_resource;
7611         for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7612
7613         if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7614             || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7615             || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7616         { /* B1 - modem */
7617                 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7618
7619                 if (bp_parms[3].length)
7620                 {
7621                         if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7622                         {
7623                                 return (_WRONG_MESSAGE_FORMAT);
7624                         }
7625
7626                         cai[2] = 0; /* Bit rate for adaptation */
7627
7628                         dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7629
7630                         PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7631                         PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7632                         PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7633                         PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7634
7635                         cai[3] = 0; /* Async framing parameters */
7636                         switch (GET_WORD(mdm_cfg[2].info))
7637                         {       /* Parity     */
7638                         case 1: /* odd parity */
7639                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7640                                 dbug(1, dprintf("MDM: odd parity"));
7641                                 break;
7642
7643                         case 2: /* even parity */
7644                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7645                                 dbug(1, dprintf("MDM: even parity"));
7646                                 break;
7647
7648                         default:
7649                                 dbug(1, dprintf("MDM: no parity"));
7650                                 break;
7651                         }
7652
7653                         switch (GET_WORD(mdm_cfg[3].info))
7654                         {       /* stop bits   */
7655                         case 1: /* 2 stop bits */
7656                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7657                                 dbug(1, dprintf("MDM: 2 stop bits"));
7658                                 break;
7659
7660                         default:
7661                                 dbug(1, dprintf("MDM: 1 stop bit"));
7662                                 break;
7663                         }
7664
7665                         switch (GET_WORD(mdm_cfg[1].info))
7666                         {     /* char length */
7667                         case 5:
7668                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7669                                 dbug(1, dprintf("MDM: 5 bits"));
7670                                 break;
7671
7672                         case 6:
7673                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7674                                 dbug(1, dprintf("MDM: 6 bits"));
7675                                 break;
7676
7677                         case 7:
7678                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7679                                 dbug(1, dprintf("MDM: 7 bits"));
7680                                 break;
7681
7682                         default:
7683                                 dbug(1, dprintf("MDM: 8 bits"));
7684                                 break;
7685                         }
7686
7687                         cai[7] = 0; /* Line taking options */
7688                         cai[8] = 0; /* Modulation negotiation options */
7689                         cai[9] = 0; /* Modulation options */
7690
7691                         if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7692                         {
7693                                 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7694                                 dbug(1, dprintf("MDM: Reverse direction"));
7695                         }
7696
7697                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7698                         {
7699                                 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7700                                 dbug(1, dprintf("MDM: Disable retrain"));
7701                         }
7702
7703                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7704                         {
7705                                 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7706                                 dbug(1, dprintf("MDM: Disable ring tone"));
7707                         }
7708
7709                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7710                         {
7711                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7712                                 dbug(1, dprintf("MDM: 1800 guard tone"));
7713                         }
7714                         else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7715                         {
7716                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7717                                 dbug(1, dprintf("MDM: 550 guard tone"));
7718                         }
7719
7720                         if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7721                         {
7722                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7723                                 dbug(1, dprintf("MDM: V100"));
7724                         }
7725                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7726                         {
7727                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7728                                 dbug(1, dprintf("MDM: IN CLASS"));
7729                         }
7730                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7731                         {
7732                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7733                                 dbug(1, dprintf("MDM: DISABLED"));
7734                         }
7735                         cai[0] = 20;
7736
7737                         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7738                             && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7739                         {
7740                                 plci->requested_options |= 1L << PRIVATE_V18;
7741                         }
7742                         if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7743                                 plci->requested_options |= 1L << PRIVATE_VOWN;
7744
7745                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7746                             & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7747                         {
7748                                 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7749                                 {
7750                                         i = 27;
7751                                         if (mdm_cfg[6].length >= 4)
7752                                         {
7753                                                 d = GET_DWORD(&mdm_cfg[6].info[1]);
7754                                                 cai[7] |= (byte) d;          /* line taking options */
7755                                                 cai[9] |= (byte)(d >> 8);    /* modulation options */
7756                                                 cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7757                                                 cai[++i] = (byte)(d >> 24);
7758                                                 if (mdm_cfg[6].length >= 8)
7759                                                 {
7760                                                         d = GET_DWORD(&mdm_cfg[6].info[5]);
7761                                                         cai[10] |= (byte) d;        /* disabled modulations mask */
7762                                                         cai[11] |= (byte)(d >> 8);
7763                                                         if (mdm_cfg[6].length >= 12)
7764                                                         {
7765                                                                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7766                                                                 cai[12] = (byte) d;          /* enabled modulations mask */
7767                                                                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7768                                                                 cai[++i] = (byte)(d >> 16);
7769                                                                 cai[++i] = (byte)(d >> 24);
7770                                                                 cai[++i] = 0;
7771                                                                 if (mdm_cfg[6].length >= 14)
7772                                                                 {
7773                                                                         w = GET_WORD(&mdm_cfg[6].info[13]);
7774                                                                         if (w != 0)
7775                                                                                 PUT_WORD(&cai[13], w);  /* min tx speed */
7776                                                                         if (mdm_cfg[6].length >= 16)
7777                                                                         {
7778                                                                                 w = GET_WORD(&mdm_cfg[6].info[15]);
7779                                                                                 if (w != 0)
7780                                                                                         PUT_WORD(&cai[15], w);  /* max tx speed */
7781                                                                                 if (mdm_cfg[6].length >= 18)
7782                                                                                 {
7783                                                                                         w = GET_WORD(&mdm_cfg[6].info[17]);
7784                                                                                         if (w != 0)
7785                                                                                                 PUT_WORD(&cai[17], w);  /* min rx speed */
7786                                                                                         if (mdm_cfg[6].length >= 20)
7787                                                                                         {
7788                                                                                                 w = GET_WORD(&mdm_cfg[6].info[19]);
7789                                                                                                 if (w != 0)
7790                                                                                                         PUT_WORD(&cai[19], w);  /* max rx speed */
7791                                                                                                 if (mdm_cfg[6].length >= 22)
7792                                                                                                 {
7793                                                                                                         w = GET_WORD(&mdm_cfg[6].info[21]);
7794                                                                                                         cai[23] = (byte)(-((short) w));  /* transmit level */
7795                                                                                                         if (mdm_cfg[6].length >= 24)
7796                                                                                                         {
7797                                                                                                                 w = GET_WORD(&mdm_cfg[6].info[23]);
7798                                                                                                                 cai[22] |= (byte) w;        /* info options mask */
7799                                                                                                                 cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7800                                                                                                         }
7801                                                                                                 }
7802                                                                                         }
7803                                                                                 }
7804                                                                         }
7805                                                                 }
7806                                                         }
7807                                                 }
7808                                         }
7809                                         cai[27] = i - 27;
7810                                         i++;
7811                                         if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7812                                         {
7813                                                 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7814                                                 {
7815                                                         for (n = 0; n < 3; n++)
7816                                                         {
7817                                                                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7818                                                                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7819                                                                         cai[i + j] = mdm_cfg_v18[n].info[j];
7820                                                                 i += cai[i] + 1;
7821                                                         }
7822                                                 }
7823                                         }
7824                                         cai[0] = (byte)(i - 1);
7825                                 }
7826                         }
7827
7828                 }
7829         }
7830         if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7831             GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7832         {
7833                 if (bp_parms[3].length) {
7834                         dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7835                         switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7836                         case 0:
7837                         case 56000:
7838                                 if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7839                                         dbug(1, dprintf("56k sync HSCX"));
7840                                         cai[1] = 8;
7841                                         cai[2] = 0;
7842                                         cai[3] = 0;
7843                                 }
7844                                 else if (GET_WORD(bp_parms[0].info) == 2) {
7845                                         dbug(1, dprintf("56k async DSP"));
7846                                         cai[2] = 9;
7847                                 }
7848                                 break;
7849                         case 50:     cai[2] = 1;  break;
7850                         case 75:     cai[2] = 1;  break;
7851                         case 110:    cai[2] = 1;  break;
7852                         case 150:    cai[2] = 1;  break;
7853                         case 200:    cai[2] = 1;  break;
7854                         case 300:    cai[2] = 1;  break;
7855                         case 600:    cai[2] = 1;  break;
7856                         case 1200:   cai[2] = 2;  break;
7857                         case 2400:   cai[2] = 3;  break;
7858                         case 4800:   cai[2] = 4;  break;
7859                         case 7200:   cai[2] = 10; break;
7860                         case 9600:   cai[2] = 5;  break;
7861                         case 12000:  cai[2] = 13; break;
7862                         case 24000:  cai[2] = 0;  break;
7863                         case 14400:  cai[2] = 11; break;
7864                         case 19200:  cai[2] = 6;  break;
7865                         case 28800:  cai[2] = 12; break;
7866                         case 38400:  cai[2] = 7;  break;
7867                         case 48000:  cai[2] = 8;  break;
7868                         case 76:     cai[2] = 15; break;  /* 75/1200     */
7869                         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7870                         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7871
7872                         default:
7873                                 return _B1_PARM_NOT_SUPPORTED;
7874                         }
7875                         cai[3] = 0;
7876                         if (cai[1] == 13)                                        /* v.110 async */
7877                         {
7878                                 if (bp_parms[3].length >= 8)
7879                                 {
7880                                         switch (GET_WORD(&bp_parms[3].info[3]))
7881                                         {       /* char length */
7882                                         case 5:
7883                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7884                                                 break;
7885                                         case 6:
7886                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7887                                                 break;
7888                                         case 7:
7889                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7890                                                 break;
7891                                         }
7892                                         switch (GET_WORD(&bp_parms[3].info[5]))
7893                                         {       /* Parity     */
7894                                         case 1: /* odd parity */
7895                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7896                                                 break;
7897                                         case 2: /* even parity */
7898                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7899                                                 break;
7900                                         }
7901                                         switch (GET_WORD(&bp_parms[3].info[7]))
7902                                         {       /* stop bits   */
7903                                         case 1: /* 2 stop bits */
7904                                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7905                                                 break;
7906                                         }
7907                                 }
7908                         }
7909                 }
7910                 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7911                         dbug(1, dprintf("V.110 default 56k sync"));
7912                         cai[1] = 8;
7913                         cai[2] = 0;
7914                         cai[3] = 0;
7915                 }
7916                 else {
7917                         dbug(1, dprintf("V.110 default 9600 async"));
7918                         cai[2] = 5;
7919                 }
7920         }
7921         PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7922         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]));
7923 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7924
7925         add_p(plci, CAI, cai);
7926         return 0;
7927 }
7928
7929 /*------------------------------------------------------------------*/
7930 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7931 /*------------------------------------------------------------------*/
7932
7933 static word add_b23(PLCI *plci, API_PARSE *bp)
7934 {
7935         word i, fax_control_bits;
7936         byte pos, len;
7937         byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7938         API_PARSE bp_parms[8];
7939         API_PARSE *b1_config;
7940         API_PARSE *b2_config;
7941         API_PARSE b2_config_parms[8];
7942         API_PARSE *b3_config;
7943         API_PARSE b3_config_parms[6];
7944         API_PARSE global_config[2];
7945
7946         static byte llc[3] = {2,0,0};
7947         static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7948         static byte nlc[256];
7949         static byte lli[12] = {1,1};
7950
7951         const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952         const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7953
7954         const byte llc3[] = {4,3,2,2,6,6,0};
7955         const byte header[] = {0,2,3,3,0,0,0};
7956
7957         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7958         for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7959         for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7960
7961         lli[0] = 1;
7962         lli[1] = 1;
7963         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7964                 lli[1] |= 2;
7965         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7966                 lli[1] |= 4;
7967
7968         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7969                 lli[1] |= 0x10;
7970                 if (plci->rx_dma_descriptor <= 0) {
7971                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7972                         if (plci->rx_dma_descriptor >= 0)
7973                                 plci->rx_dma_descriptor++;
7974                 }
7975                 if (plci->rx_dma_descriptor > 0) {
7976                         lli[0] = 6;
7977                         lli[1] |= 0x40;
7978                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7979                         lli[3] = (byte)plci->rx_dma_magic;
7980                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
7981                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
7982                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
7983                 }
7984         }
7985
7986         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7987                 lli[1] |= 0x20;
7988         }
7989
7990         dbug(1, dprintf("add_b23"));
7991         api_save_msg(bp, "s", &plci->B_protocol);
7992
7993         if (!bp->length && plci->tel)
7994         {
7995                 plci->adv_nl = true;
7996                 dbug(1, dprintf("Default adv.Nl"));
7997                 add_p(plci, LLI, lli);
7998                 plci->B2_prot = 1 /*XPARENT*/;
7999                 plci->B3_prot = 0 /*XPARENT*/;
8000                 llc[1] = 2;
8001                 llc[2] = 4;
8002                 add_p(plci, LLC, llc);
8003                 dlc[0] = 2;
8004                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8005                 add_p(plci, DLC, dlc);
8006                 return 0;
8007         }
8008
8009         if (!bp->length) /*default*/
8010         {
8011                 dbug(1, dprintf("ret default"));
8012                 add_p(plci, LLI, lli);
8013                 plci->B2_prot = 0 /*X.75   */;
8014                 plci->B3_prot = 0 /*XPARENT*/;
8015                 llc[1] = 1;
8016                 llc[2] = 4;
8017                 add_p(plci, LLC, llc);
8018                 dlc[0] = 2;
8019                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8020                 add_p(plci, DLC, dlc);
8021                 return 0;
8022         }
8023         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8024         if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8025
8026         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8027         {
8028                 bp_parms[6].length = 0;
8029                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8030                 {
8031                         dbug(1, dprintf("b-form.!"));
8032                         return _WRONG_MESSAGE_FORMAT;
8033                 }
8034         }
8035         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8036         {
8037                 dbug(1, dprintf("b-form.!"));
8038                 return _WRONG_MESSAGE_FORMAT;
8039         }
8040
8041         if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8042         {
8043                 if (GET_WORD(bp_parms[1].info) != 1
8044                     || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8045                 plci->adv_nl = true;
8046         }
8047         else if (plci->tel) return _B2_NOT_SUPPORTED;
8048
8049
8050         if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8051             && (GET_WORD(bp_parms[2].info) == B3_RTP)
8052             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8053         {
8054                 add_p(plci, LLI, lli);
8055                 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8056                 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8057                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8058                 llc[2] = 4;
8059                 add_p(plci, LLC, llc);
8060                 dlc[0] = 2;
8061                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8062                 dlc[3] = 3; /* Addr A */
8063                 dlc[4] = 1; /* Addr B */
8064                 dlc[5] = 7; /* modulo mode */
8065                 dlc[6] = 7; /* window size */
8066                 dlc[7] = 0; /* XID len Lo  */
8067                 dlc[8] = 0; /* XID len Hi  */
8068                 for (i = 0; i < bp_parms[4].length; i++)
8069                         dlc[9 + i] = bp_parms[4].info[1 + i];
8070                 dlc[0] = (byte)(8 + bp_parms[4].length);
8071                 add_p(plci, DLC, dlc);
8072                 for (i = 0; i < bp_parms[5].length; i++)
8073                         nlc[1 + i] = bp_parms[5].info[1 + i];
8074                 nlc[0] = (byte)(bp_parms[5].length);
8075                 add_p(plci, NLC, nlc);
8076                 return 0;
8077         }
8078
8079
8080
8081         if ((GET_WORD(bp_parms[1].info) >= 32)
8082             || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8083                 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8084                     || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8085
8086         {
8087                 return _B2_NOT_SUPPORTED;
8088         }
8089         if ((GET_WORD(bp_parms[2].info) >= 32)
8090             || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8091         {
8092                 return _B3_NOT_SUPPORTED;
8093         }
8094         if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8095             && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8096                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8097                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8098         {
8099                 return (add_modem_b23(plci, bp_parms));
8100         }
8101
8102         add_p(plci, LLI, lli);
8103
8104         plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8105         plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8106         if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8107
8108         if (bp_parms[6].length)
8109         {
8110                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8111                 {
8112                         return _WRONG_MESSAGE_FORMAT;
8113                 }
8114                 switch (GET_WORD(global_config[0].info))
8115                 {
8116                 case 1:
8117                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8118                         break;
8119                 case 2:
8120                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8121                         break;
8122                 }
8123         }
8124         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8125
8126
8127         if (plci->B2_prot == B2_PIAFS)
8128                 llc[1] = PIAFS_CRC;
8129         else
8130 /* IMPLEMENT_PIAFS */
8131         {
8132                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8133                         llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8134         }
8135         llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8136
8137         add_p(plci, LLC, llc);
8138
8139         dlc[0] = 2;
8140         PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8141                  header[GET_WORD(bp_parms[2].info)]);
8142
8143         b1_config = &bp_parms[3];
8144         nlc[0] = 0;
8145         if (plci->B3_prot == 4
8146             || plci->B3_prot == 5)
8147         {
8148                 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8149                 nlc[0] = sizeof(T30_INFO);
8150                 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8151                         ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8152                 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8153                 if (b1_config->length >= 2)
8154                 {
8155                         ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8156                 }
8157         }
8158         b2_config = &bp_parms[4];
8159
8160
8161         if (llc[1] == PIAFS_CRC)
8162         {
8163                 if (plci->B3_prot != B3_TRANSPARENT)
8164                 {
8165                         return _B_STACK_NOT_SUPPORTED;
8166                 }
8167                 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8168                         return _WRONG_MESSAGE_FORMAT;
8169                 }
8170                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8171                 dlc[3] = 0; /* Addr A */
8172                 dlc[4] = 0; /* Addr B */
8173                 dlc[5] = 0; /* modulo mode */
8174                 dlc[6] = 0; /* window size */
8175                 if (b2_config->length >= 7) {
8176                         dlc[7] = 7;
8177                         dlc[8] = 0;
8178                         dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8179                         dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8180                         dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8181                         dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8182                         dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8183                         dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8184                         dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8185                         dlc[0] = 15;
8186                         if (b2_config->length >= 8) { /* PIAFS control abilities */
8187                                 dlc[7] = 10;
8188                                 dlc[16] = 2; /* Length of PIAFS extension */
8189                                 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8190                                 dlc[18] = b2_config_parms[4].info[0]; /* value */
8191                                 dlc[0] = 18;
8192                         }
8193                 }
8194                 else /* default values, 64K, variable, no compression */
8195                 {
8196                         dlc[7] = 7;
8197                         dlc[8] = 0;
8198                         dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8199                         dlc[10] = 0x03; /* V.42bis P0 */
8200                         dlc[11] = 0;    /* V.42bis P0 */
8201                         dlc[12] = 0;    /* V.42bis P1 */
8202                         dlc[13] = 0;    /* V.42bis P1 */
8203                         dlc[14] = 0;    /* V.42bis P2 */
8204                         dlc[15] = 0;    /* V.42bis P2 */
8205                         dlc[0] = 15;
8206                 }
8207                 add_p(plci, DLC, dlc);
8208         }
8209         else
8210
8211                 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8212                 {
8213                         if (plci->B3_prot != B3_TRANSPARENT)
8214                                 return _B_STACK_NOT_SUPPORTED;
8215
8216                         dlc[0] = 6;
8217                         PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8218                         dlc[3] = 0x08;
8219                         dlc[4] = 0x01;
8220                         dlc[5] = 127;
8221                         dlc[6] = 7;
8222                         if (b2_config->length != 0)
8223                         {
8224                                 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8225                                         return _WRONG_MESSAGE_FORMAT;
8226                                 }
8227                                 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8228                                 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8229                                 if (b2_config->info[3] != 128)
8230                                 {
8231                                         dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8232                                         return _B2_PARM_NOT_SUPPORTED;
8233                                 }
8234                                 dlc[5] = (byte)(b2_config->info[3] - 1);
8235                                 dlc[6] = b2_config->info[4];
8236                                 if (llc[1] == V120_V42BIS) {
8237                                         if (b2_config->length >= 10) {
8238                                                 dlc[7] = 6;
8239                                                 dlc[8] = 0;
8240                                                 dlc[9] = b2_config_parms[4].info[0];
8241                                                 dlc[10] = b2_config_parms[4].info[1];
8242                                                 dlc[11] = b2_config_parms[5].info[0];
8243                                                 dlc[12] = b2_config_parms[5].info[1];
8244                                                 dlc[13] = b2_config_parms[6].info[0];
8245                                                 dlc[14] = b2_config_parms[6].info[1];
8246                                                 dlc[0] = 14;
8247                                                 dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8248                                                 dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8249                                                 dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8250                                         }
8251                                         else {
8252                                                 dlc[6] = 14;
8253                                         }
8254                                 }
8255                         }
8256                 }
8257                 else
8258                 {
8259                         if (b2_config->length)
8260                         {
8261                                 dbug(1, dprintf("B2-Config"));
8262                                 if (llc[1] == X75_V42BIS) {
8263                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8264                                         {
8265                                                 return _WRONG_MESSAGE_FORMAT;
8266                                         }
8267                                 }
8268                                 else {
8269                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8270                                         {
8271                                                 return _WRONG_MESSAGE_FORMAT;
8272                                         }
8273                                 }
8274                                 /* if B2 Protocol is LAPD, b2_config structure is different */
8275                                 if (llc[1] == 6)
8276                                 {
8277                                         dlc[0] = 4;
8278                                         if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8279                                         else dlc[2] = 0x01;
8280                                         if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8281                                         {
8282                                                 SAPI = b2_config->info[2];    /* SAPI */
8283                                         }
8284                                         dlc[1] = SAPI;
8285                                         if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8286                                         {
8287                                                 dlc[3] = 127;      /* Mode */
8288                                         }
8289                                         else
8290                                         {
8291                                                 dlc[3] = 7;        /* Mode */
8292                                         }
8293
8294                                         if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8295                                         else dlc[4] = 1;
8296                                         dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8297                                         if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8298                                 }
8299                                 else
8300                                 {
8301                                         dlc[0] = (byte)(b2_config_parms[4].length + 6);
8302                                         dlc[3] = b2_config->info[1];
8303                                         dlc[4] = b2_config->info[2];
8304                                         if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8305                                                 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8306                                                 return _B2_PARM_NOT_SUPPORTED;
8307                                         }
8308
8309                                         dlc[5] = (byte)(b2_config->info[3] - 1);
8310                                         dlc[6] = b2_config->info[4];
8311                                         if (dlc[6] > dlc[5]) {
8312                                                 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]));
8313                                                 return _B2_PARM_NOT_SUPPORTED;
8314                                         }
8315
8316                                         if (llc[1] == X75_V42BIS) {
8317                                                 if (b2_config->length >= 10) {
8318                                                         dlc[7] = 6;
8319                                                         dlc[8] = 0;
8320                                                         dlc[9] = b2_config_parms[4].info[0];
8321                                                         dlc[10] = b2_config_parms[4].info[1];
8322                                                         dlc[11] = b2_config_parms[5].info[0];
8323                                                         dlc[12] = b2_config_parms[5].info[1];
8324                                                         dlc[13] = b2_config_parms[6].info[0];
8325                                                         dlc[14] = b2_config_parms[6].info[1];
8326                                                         dlc[0] = 14;
8327                                                         dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8328                                                         dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8329                                                         dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8330                                                 }
8331                                                 else {
8332                                                         dlc[6] = 14;
8333                                                 }
8334
8335                                         }
8336                                         else {
8337                                                 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8338                                                 for (i = 0; i < b2_config_parms[4].length; i++)
8339                                                         dlc[11 + i] = b2_config_parms[4].info[1 + i];
8340                                         }
8341                                 }
8342                         }
8343                 }
8344         add_p(plci, DLC, dlc);
8345
8346         b3_config = &bp_parms[5];
8347         if (b3_config->length)
8348         {
8349                 if (plci->B3_prot == 4
8350                     || plci->B3_prot == 5)
8351                 {
8352                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8353                         {
8354                                 return _WRONG_MESSAGE_FORMAT;
8355                         }
8356                         i = GET_WORD((byte *)(b3_config_parms[0].info));
8357                         ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8358                                                                     ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8359                         ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8360                         fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8361                         if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8362                                 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8363                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8364                         {
8365
8366                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8367                                     & (1L << PRIVATE_FAX_PAPER_FORMATS))
8368                                 {
8369                                         ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8370                                                 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8371                                                 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8372                                 }
8373
8374                                 ((T30_INFO *)&nlc[1])->recording_properties =
8375                                         T30_RECORDING_WIDTH_ISO_A3 |
8376                                         (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8377                                         (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8378                         }
8379                         if (plci->B3_prot == 5)
8380                         {
8381                                 if (i & 0x0002) /* Accept incoming fax-polling requests */
8382                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8383                                 if (i & 0x2000) /* Do not use MR compression */
8384                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8385                                 if (i & 0x4000) /* Do not use MMR compression */
8386                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8387                                 if (i & 0x8000) /* Do not use ECM */
8388                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8389                                 if (plci->fax_connect_info_length != 0)
8390                                 {
8391                                         ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8392                                         ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8393                                         ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8394                                         fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8395                                                 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8396                                 }
8397                         }
8398                         /* copy station id to NLC */
8399                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8400                         {
8401                                 if (i < b3_config_parms[2].length)
8402                                 {
8403                                         ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8404                                 }
8405                                 else
8406                                 {
8407                                         ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8408                                 }
8409                         }
8410                         ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8411                         /* copy head line to NLC */
8412                         if (b3_config_parms[3].length)
8413                         {
8414
8415                                 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8416                                 if (pos != 0)
8417                                 {
8418                                         if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8419                                                 pos = 0;
8420                                         else
8421                                         {
8422                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8423                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8424                                                 len = (byte)b3_config_parms[2].length;
8425                                                 if (len > 20)
8426                                                         len = 20;
8427                                                 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8428                                                 {
8429                                                         for (i = 0; i < len; i++)
8430                                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8431                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8432                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8433                                                 }
8434                                         }
8435                                 }
8436
8437                                 len = (byte)b3_config_parms[3].length;
8438                                 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8439                                         len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8440                                 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8441                                 nlc[0] += (byte)(pos + len);
8442                                 for (i = 0; i < len; i++)
8443                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8444                         } else
8445                                 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8446
8447                         plci->nsf_control_bits = 0;
8448                         if (plci->B3_prot == 5)
8449                         {
8450                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8451                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8452                                 {
8453                                         plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8454                                 }
8455                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8456                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8457                                 {
8458                                         plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8459                                 }
8460                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8461                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8462                                 {
8463                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8464                                             & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8465                                         {
8466                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8467                                                 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8468                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8469                                         }
8470                                         len = nlc[0];
8471                                         pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8472                                         if (pos < plci->fax_connect_info_length)
8473                                         {
8474                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476                                         }
8477                                         else
8478                                                 nlc[++len] = 0;
8479                                         if (pos < plci->fax_connect_info_length)
8480                                         {
8481                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8482                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8483                                         }
8484                                         else
8485                                                 nlc[++len] = 0;
8486                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8487                                             & (1L << PRIVATE_FAX_NONSTANDARD))
8488                                         {
8489                                                 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8490                                                 {
8491                                                         if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8492                                                                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8493                                                         for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8494                                                                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8495                                                 }
8496                                                 else
8497                                                 {
8498                                                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8499                                                         {
8500                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8501                                                                 nlc[++len] = 0;
8502                                                         }
8503                                                         else
8504                                                         {
8505                                                                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8506                                                                         plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8507                                                                 nlc[++len] = (byte)(b3_config_parms[4].length);
8508                                                                 for (i = 0; i < b3_config_parms[4].length; i++)
8509                                                                         nlc[++len] = b3_config_parms[4].info[1 + i];
8510                                                         }
8511                                                 }
8512                                         }
8513                                         nlc[0] = len;
8514                                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8515                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8516                                         {
8517                                                 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8518                                         }
8519                                 }
8520                         }
8521
8522                         PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8523                         len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8524                         for (i = 0; i < len; i++)
8525                                 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8526                         ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8527                         i += ((T30_INFO *)&nlc[1])->head_line_len;
8528                         while (i < nlc[0])
8529                                 plci->fax_connect_info_buffer[len++] = nlc[++i];
8530                         plci->fax_connect_info_length = len;
8531                 }
8532                 else
8533                 {
8534                         nlc[0] = 14;
8535                         if (b3_config->length != 16)
8536                                 return _B3_PARM_NOT_SUPPORTED;
8537                         for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8538                         if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8539                                 return _B3_PARM_NOT_SUPPORTED;
8540                         nlc[13] = b3_config->info[13];
8541                         if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8542                                 return _B3_PARM_NOT_SUPPORTED;
8543                         nlc[14] = b3_config->info[15];
8544                 }
8545         }
8546         else
8547         {
8548                 if (plci->B3_prot == 4
8549                     || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8550         }
8551         add_p(plci, NLC, nlc);
8552         return 0;
8553 }
8554
8555 /*----------------------------------------------------------------*/
8556 /*      make the same as add_b23, but only for the modem related  */
8557 /*      L2 and L3 B-Chan protocol.                                */
8558 /*                                                                */
8559 /*      Enabled L2 and L3 Configurations:                         */
8560 /*        If L1 == Modem all negotiation                          */
8561 /*          only L2 == Modem with full negotiation is allowed     */
8562 /*        If L1 == Modem async or sync                            */
8563 /*          only L2 == Transparent is allowed                     */
8564 /*        L3 == Modem or L3 == Transparent are allowed            */
8565 /*      B2 Configuration for modem:                               */
8566 /*          word : enable/disable compression, bitoptions         */
8567 /*      B3 Configuration for modem:                               */
8568 /*          empty                                                 */
8569 /*----------------------------------------------------------------*/
8570 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8571 {
8572         static byte lli[12] = {1,1};
8573         static byte llc[3] = {2,0,0};
8574         static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8575         API_PARSE mdm_config[2];
8576         word i;
8577         word b2_config = 0;
8578
8579         for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8580         for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8581
8582         if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8583              && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8584             || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8585                 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8586         {
8587                 return (_B_STACK_NOT_SUPPORTED);
8588         }
8589         if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8590             && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8591         {
8592                 return (_B_STACK_NOT_SUPPORTED);
8593         }
8594
8595         plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8596         plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8597
8598         if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8599         {
8600                 if (api_parse(&bp_parms[4].info[1],
8601                               (word)bp_parms[4].length, "w",
8602                               mdm_config))
8603                 {
8604                         return (_WRONG_MESSAGE_FORMAT);
8605                 }
8606                 b2_config = GET_WORD(mdm_config[0].info);
8607         }
8608
8609         /* OK, L2 is modem */
8610
8611         lli[0] = 1;
8612         lli[1] = 1;
8613         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8614                 lli[1] |= 2;
8615         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8616                 lli[1] |= 4;
8617
8618         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8619                 lli[1] |= 0x10;
8620                 if (plci->rx_dma_descriptor <= 0) {
8621                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8622                         if (plci->rx_dma_descriptor >= 0)
8623                                 plci->rx_dma_descriptor++;
8624                 }
8625                 if (plci->rx_dma_descriptor > 0) {
8626                         lli[1] |= 0x40;
8627                         lli[0] = 6;
8628                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8629                         lli[3] = (byte)plci->rx_dma_magic;
8630                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
8631                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
8632                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
8633                 }
8634         }
8635
8636         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8637                 lli[1] |= 0x20;
8638         }
8639
8640         llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8641                 /*V42*/ 10 : /*V42_IN*/ 9;
8642         llc[2] = 4;                      /* pass L3 always transparent */
8643         add_p(plci, LLI, lli);
8644         add_p(plci, LLC, llc);
8645         i =  1;
8646         PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8647         i += 2;
8648         if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8649         {
8650                 if (bp_parms[4].length)
8651                 {
8652                         dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8653                         dlc[i++] = 3; /* Addr A */
8654                         dlc[i++] = 1; /* Addr B */
8655                         dlc[i++] = 7; /* modulo mode */
8656                         dlc[i++] = 7; /* window size */
8657                         dlc[i++] = 0; /* XID len Lo  */
8658                         dlc[i++] = 0; /* XID len Hi  */
8659
8660                         if (b2_config & MDM_B2_DISABLE_V42bis)
8661                         {
8662                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8663                         }
8664                         if (b2_config & MDM_B2_DISABLE_MNP)
8665                         {
8666                                 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8667                         }
8668                         if (b2_config & MDM_B2_DISABLE_TRANS)
8669                         {
8670                                 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8671                         }
8672                         if (b2_config & MDM_B2_DISABLE_V42)
8673                         {
8674                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8675                         }
8676                         if (b2_config & MDM_B2_DISABLE_COMP)
8677                         {
8678                                 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8679                         }
8680                         i++;
8681                 }
8682         }
8683         else
8684         {
8685                 dlc[i++] = 3; /* Addr A */
8686                 dlc[i++] = 1; /* Addr B */
8687                 dlc[i++] = 7; /* modulo mode */
8688                 dlc[i++] = 7; /* window size */
8689                 dlc[i++] = 0; /* XID len Lo  */
8690                 dlc[i++] = 0; /* XID len Hi  */
8691                 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8692                         DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8693                         DLC_MODEMPROT_DISABLE_V42_DETECT |
8694                         DLC_MODEMPROT_DISABLE_COMPRESSION;
8695         }
8696         dlc[0] = (byte)(i - 1);
8697 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8698         add_p(plci, DLC, dlc);
8699         return (0);
8700 }
8701
8702
8703 /*------------------------------------------------------------------*/
8704 /* send a request for the signaling entity                          */
8705 /*------------------------------------------------------------------*/
8706
8707 static void sig_req(PLCI *plci, byte req, byte Id)
8708 {
8709         if (!plci) return;
8710         if (plci->adapter->adapter_disabled) return;
8711         dbug(1, dprintf("sig_req(%x)", req));
8712         if (req == REMOVE)
8713                 plci->sig_remove_id = plci->Sig.Id;
8714         if (plci->req_in == plci->req_in_start) {
8715                 plci->req_in += 2;
8716                 plci->RBuffer[plci->req_in++] = 0;
8717         }
8718         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8719         plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8720         plci->RBuffer[plci->req_in++] = req;  /* request */
8721         plci->RBuffer[plci->req_in++] = 0;    /* channel */
8722         plci->req_in_start = plci->req_in;
8723 }
8724
8725 /*------------------------------------------------------------------*/
8726 /* send a request for the network layer entity                      */
8727 /*------------------------------------------------------------------*/
8728
8729 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8730 {
8731         if (!plci) return;
8732         if (plci->adapter->adapter_disabled) return;
8733         dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8734         if (req == REMOVE)
8735         {
8736                 plci->nl_remove_id = plci->NL.Id;
8737                 ncci_remove(plci, 0, (byte)(ncci != 0));
8738                 ncci = 0;
8739         }
8740         if (plci->req_in == plci->req_in_start) {
8741                 plci->req_in += 2;
8742                 plci->RBuffer[plci->req_in++] = 0;
8743         }
8744         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8745         plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8746         plci->RBuffer[plci->req_in++] = req;  /* request */
8747         plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8748         plci->req_in_start = plci->req_in;
8749 }
8750
8751 static void send_req(PLCI *plci)
8752 {
8753         ENTITY *e;
8754         word l;
8755 /*  word i; */
8756
8757         if (!plci) return;
8758         if (plci->adapter->adapter_disabled) return;
8759         channel_xmit_xon(plci);
8760
8761         /* if nothing to do, return */
8762         if (plci->req_in == plci->req_out) return;
8763         dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8764
8765         if (plci->nl_req || plci->sig_req) return;
8766
8767         l = GET_WORD(&plci->RBuffer[plci->req_out]);
8768         plci->req_out += 2;
8769         plci->XData[0].P = &plci->RBuffer[plci->req_out];
8770         plci->req_out += l;
8771         if (plci->RBuffer[plci->req_out] == 1)
8772         {
8773                 e = &plci->NL;
8774                 plci->req_out++;
8775                 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8776                 e->ReqCh = plci->RBuffer[plci->req_out++];
8777                 if (!(e->Id & 0x1f))
8778                 {
8779                         e->Id = NL_ID;
8780                         plci->RBuffer[plci->req_out - 4] = CAI;
8781                         plci->RBuffer[plci->req_out - 3] = 1;
8782                         plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8783                         plci->RBuffer[plci->req_out - 1] = 0;
8784                         l += 3;
8785                         plci->nl_global_req = plci->nl_req;
8786                 }
8787                 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8788         }
8789         else
8790         {
8791                 e = &plci->Sig;
8792                 if (plci->RBuffer[plci->req_out])
8793                         e->Id = plci->RBuffer[plci->req_out];
8794                 plci->req_out++;
8795                 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8796                 e->ReqCh = plci->RBuffer[plci->req_out++];
8797                 if (!(e->Id & 0x1f))
8798                         plci->sig_global_req = plci->sig_req;
8799                 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8800         }
8801         plci->XData[0].PLength = l;
8802         e->X = plci->XData;
8803         plci->adapter->request(e);
8804         dbug(1, dprintf("send_ok"));
8805 }
8806
8807 static void send_data(PLCI *plci)
8808 {
8809         DIVA_CAPI_ADAPTER *a;
8810         DATA_B3_DESC *data;
8811         NCCI   *ncci_ptr;
8812         word ncci;
8813
8814         if (!plci->nl_req && plci->ncci_ring_list)
8815         {
8816                 a = plci->adapter;
8817                 ncci = plci->ncci_ring_list;
8818                 do
8819                 {
8820                         ncci = a->ncci_next[ncci];
8821                         ncci_ptr = &(a->ncci[ncci]);
8822                         if (!(a->ncci_ch[ncci]
8823                               && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8824                         {
8825                                 if (ncci_ptr->data_pending)
8826                                 {
8827                                         if ((a->ncci_state[ncci] == CONNECTED)
8828                                             || (a->ncci_state[ncci] == INC_ACT_PENDING)
8829                                             || (plci->send_disc == ncci))
8830                                         {
8831                                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8832                                                 if ((plci->B2_prot == B2_V120_ASYNC)
8833                                                     || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8834                                                     || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8835                                                 {
8836                                                         plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8837                                                         plci->NData[1].PLength = data->Length;
8838                                                         if (data->Flags & 0x10)
8839                                                                 plci->NData[0].P = v120_break_header;
8840                                                         else
8841                                                                 plci->NData[0].P = v120_default_header;
8842                                                         plci->NData[0].PLength = 1;
8843                                                         plci->NL.XNum = 2;
8844                                                         plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8845                                                 }
8846                                                 else
8847                                                 {
8848                                                         plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8849                                                         plci->NData[0].PLength = data->Length;
8850                                                         if (data->Flags & 0x10)
8851                                                                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8852
8853                                                         else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8854                                                                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8855
8856                                                         else
8857                                                                 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8858                                                 }
8859                                                 plci->NL.X = plci->NData;
8860                                                 plci->NL.ReqCh = a->ncci_ch[ncci];
8861                                                 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8862                                                 plci->data_sent = true;
8863                                                 plci->data_sent_ptr = data->P;
8864                                                 a->request(&plci->NL);
8865                                         }
8866                                         else {
8867                                                 cleanup_ncci_data(plci, ncci);
8868                                         }
8869                                 }
8870                                 else if (plci->send_disc == ncci)
8871                                 {
8872                                         /* dprintf("N_DISC"); */
8873                                         plci->NData[0].PLength = 0;
8874                                         plci->NL.ReqCh = a->ncci_ch[ncci];
8875                                         plci->NL.Req = plci->nl_req = N_DISC;
8876                                         a->request(&plci->NL);
8877                                         plci->command = _DISCONNECT_B3_R;
8878                                         plci->send_disc = 0;
8879                                 }
8880                         }
8881                 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8882                 plci->ncci_ring_list = ncci;
8883         }
8884 }
8885
8886 static void listen_check(DIVA_CAPI_ADAPTER *a)
8887 {
8888         word i, j;
8889         PLCI *plci;
8890         byte activnotifiedcalls = 0;
8891
8892         dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8893         if (!remove_started && !a->adapter_disabled)
8894         {
8895                 for (i = 0; i < a->max_plci; i++)
8896                 {
8897                         plci = &(a->plci[i]);
8898                         if (plci->notifiedcall) activnotifiedcalls++;
8899                 }
8900                 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8901
8902                 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8903                         if ((j = get_plci(a))) {
8904                                 a->listen_active++;
8905                                 plci = &a->plci[j - 1];
8906                                 plci->State = LISTENING;
8907
8908                                 add_p(plci, OAD, "\x01\xfd");
8909
8910                                 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8911
8912                                 add_p(plci, CAI, "\x01\xc0");
8913                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8914                                 add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8915                                 add_p(plci, SHIFT | 6, NULL);
8916                                 add_p(plci, SIN, "\x02\x00\x00");
8917                                 plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8918                                 sig_req(plci, ASSIGN, DSIG_ID);
8919                                 send_req(plci);
8920                         }
8921                 }
8922         }
8923 }
8924
8925 /*------------------------------------------------------------------*/
8926 /* functions for all parameters sent in INDs                        */
8927 /*------------------------------------------------------------------*/
8928
8929 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8930 {
8931         word ploc;            /* points to current location within packet */
8932         byte w;
8933         byte wlen;
8934         byte codeset, lock;
8935         byte *in;
8936         word i;
8937         word code;
8938         word mIEindex = 0;
8939         ploc = 0;
8940         codeset = 0;
8941         lock = 0;
8942
8943         in = plci->Sig.RBuffer->P;
8944         for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8945         {                            /* element but parms array is larger      */
8946                 parms[i] = (byte *)"";
8947         }
8948         for (i = 0; i < multiIEsize; i++)
8949         {
8950                 parms[i] = (byte *)"";
8951         }
8952
8953         while (ploc < plci->Sig.RBuffer->length - 1) {
8954
8955                 /* read information element id and length                   */
8956                 w = in[ploc];
8957
8958                 if (w & 0x80) {
8959 /*    w &=0xf0; removed, cannot detect congestion levels */
8960 /*    upper 4 bit masked with w==SHIFT now               */
8961                         wlen = 0;
8962                 }
8963                 else {
8964                         wlen = (byte)(in[ploc + 1] + 1);
8965                 }
8966                 /* check if length valid (not exceeding end of packet)      */
8967                 if ((ploc + wlen) > 270) return;
8968                 if (lock & 0x80) lock &= 0x7f;
8969                 else codeset = lock;
8970
8971                 if ((w & 0xf0) == SHIFT) {
8972                         codeset = in[ploc];
8973                         if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8974                         codeset &= 7;
8975                         lock |= 0x80;
8976                 }
8977                 else {
8978                         if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8979                         else code = w;
8980                         code |= (codeset << 8);
8981
8982                         for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8983
8984                         if (i < parms_id[0] + 1) {
8985                                 if (!multiIEsize) { /* with multiIEs use next field index,          */
8986                                         mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8987                                 }
8988
8989                                 parms[mIEindex] = &in[ploc + 1];
8990                                 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8991                                 if (parms_id[i] == OAD
8992                                     || parms_id[i] == CONN_NR
8993                                     || parms_id[i] == CAD) {
8994                                         if (in[ploc + 2] & 0x80) {
8995                                                 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8996                                                 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8997                                                 in[ploc + 2] = 0x80;
8998                                                 parms[mIEindex] = &in[ploc];
8999                                         }
9000                                 }
9001                                 mIEindex++;       /* effects multiIEs only */
9002                         }
9003                 }
9004
9005                 ploc += (wlen + 1);
9006         }
9007         return;
9008 }
9009
9010 /*------------------------------------------------------------------*/
9011 /* try to match a cip from received BC and HLC                      */
9012 /*------------------------------------------------------------------*/
9013
9014 static byte ie_compare(byte *ie1, byte *ie2)
9015 {
9016         word i;
9017         if (!ie1 || !ie2) return false;
9018         if (!ie1[0]) return false;
9019         for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9020         return true;
9021 }
9022
9023 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9024 {
9025         word i;
9026         word j;
9027
9028         for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9029
9030         for (j = 16; j < 29 &&
9031                      (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9032         if (j == 29) return i;
9033         return j;
9034 }
9035
9036
9037 static byte AddInfo(byte **add_i,
9038                     byte **fty_i,
9039                     byte *esc_chi,
9040                     byte *facility)
9041 {
9042         byte i;
9043         byte j;
9044         byte k;
9045         byte flen;
9046         byte len = 0;
9047         /* facility is a nested structure */
9048         /* FTY can be more than once      */
9049
9050         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9051         {
9052                 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9053         }
9054
9055         else
9056         {
9057                 add_i[0] = (byte *)"";
9058         }
9059         if (!fty_i[0][0])
9060         {
9061                 add_i[3] = (byte *)"";
9062         }
9063         else
9064         {    /* facility array found  */
9065                 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9066                 {
9067                         dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9068                         len += fty_i[i][0];
9069                         len += 2;
9070                         flen = fty_i[i][0];
9071                         facility[j++] = 0x1c; /* copy fac IE */
9072                         for (k = 0; k <= flen; k++, j++)
9073                         {
9074                                 facility[j] = fty_i[i][k];
9075 /*      dbug(1, dprintf("%x ",facility[j])); */
9076                         }
9077                 }
9078                 facility[0] = len;
9079                 add_i[3] = facility;
9080         }
9081 /*  dbug(1, dprintf("FacArrLen=%d ",len)); */
9082         len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9083         len += 4;                          /* calculate length of all */
9084         return (len);
9085 }
9086
9087 /*------------------------------------------------------------------*/
9088 /* voice and codec features                                         */
9089 /*------------------------------------------------------------------*/
9090
9091 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9092 {
9093         byte voice_chi[] = "\x02\x18\x01";
9094         byte channel;
9095
9096         channel = chi[chi[0]] & 0x3;
9097         dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9098         voice_chi[2] = (channel) ? channel : 1;
9099         add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
9100         add_p(plci, ESC, voice_chi);                  /* Channel */
9101         sig_req(plci, TEL_CTRL, 0);
9102         send_req(plci);
9103         if (a->AdvSignalPLCI)
9104         {
9105                 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9106         }
9107 }
9108
9109 static void VoiceChannelOff(PLCI *plci)
9110 {
9111         dbug(1, dprintf("ExtDevOFF"));
9112         add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
9113         sig_req(plci, TEL_CTRL, 0);
9114         send_req(plci);
9115         if (plci->adapter->AdvSignalPLCI)
9116         {
9117                 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9118         }
9119 }
9120
9121
9122 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9123                             byte hook_listen)
9124 {
9125         word j;
9126         PLCI *splci;
9127
9128         /* check if hardware supports handset with hook states (adv.codec) */
9129         /* or if just a on board codec is supported                        */
9130         /* the advanced codec plci is just for internal use                */
9131
9132         /* diva Pro with on-board codec:                                   */
9133         if (a->profile.Global_Options & HANDSET)
9134         {
9135                 /* new call, but hook states are already signalled */
9136                 if (a->AdvCodecFLAG)
9137                 {
9138                         if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9139                         {
9140                                 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9141                                 return 0x2001; /* codec in use by another application */
9142                         }
9143                         if (plci != NULL)
9144                         {
9145                                 a->AdvSignalPLCI = plci;
9146                                 plci->tel = ADV_VOICE;
9147                         }
9148                         return 0;                      /* adv codec still used */
9149                 }
9150                 if ((j = get_plci(a)))
9151                 {
9152                         splci = &a->plci[j - 1];
9153                         splci->tel = CODEC_PERMANENT;
9154                         /* hook_listen indicates if a facility_req with handset/hook support */
9155                         /* was sent. Otherwise if just a call on an external device was made */
9156                         /* the codec will be used but the hook info will be discarded (just  */
9157                         /* the external controller is in use                                 */
9158                         if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9159                         else
9160                         {
9161                                 splci->State = ADVANCED_VOICE_NOSIG;
9162                                 if (plci)
9163                                 {
9164                                         plci->spoofed_msg = SPOOFING_REQUIRED;
9165                                 }
9166                                 /* indicate D-ch connect if  */
9167                         }                                        /* codec is connected OK     */
9168                         if (plci != NULL)
9169                         {
9170                                 a->AdvSignalPLCI = plci;
9171                                 plci->tel = ADV_VOICE;
9172                         }
9173                         a->AdvSignalAppl = appl;
9174                         a->AdvCodecFLAG = true;
9175                         a->AdvCodecPLCI = splci;
9176                         add_p(splci, CAI, "\x01\x15");
9177                         add_p(splci, LLI, "\x01\x00");
9178                         add_p(splci, ESC, "\x02\x18\x00");
9179                         add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9180                         splci->internal_command = PERM_COD_ASSIGN;
9181                         dbug(1, dprintf("Codec Assign"));
9182                         sig_req(splci, ASSIGN, DSIG_ID);
9183                         send_req(splci);
9184                 }
9185                 else
9186                 {
9187                         return 0x2001; /* wrong state, no more plcis */
9188                 }
9189         }
9190         else if (a->profile.Global_Options & ON_BOARD_CODEC)
9191         {
9192                 if (hook_listen) return 0x300B;               /* Facility not supported */
9193                 /* no hook with SCOM      */
9194                 if (plci != NULL) plci->tel = CODEC;
9195                 dbug(1, dprintf("S/SCOM codec"));
9196                 /* first time we use the scom-s codec we must shut down the internal   */
9197                 /* handset application of the card. This can be done by an assign with */
9198                 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9199                 if (!a->scom_appl_disable) {
9200                         if ((j = get_plci(a))) {
9201                                 splci = &a->plci[j - 1];
9202                                 add_p(splci, CAI, "\x01\x80");
9203                                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9204                                 sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9205                                 send_req(splci);
9206                                 a->scom_appl_disable = true;
9207                         }
9208                         else{
9209                                 return 0x2001; /* wrong state, no more plcis */
9210                         }
9211                 }
9212         }
9213         else return 0x300B;               /* Facility not supported */
9214
9215         return 0;
9216 }
9217
9218
9219 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9220 {
9221
9222         dbug(1, dprintf("CodecIdCheck"));
9223
9224         if (a->AdvSignalPLCI == plci)
9225         {
9226                 dbug(1, dprintf("PLCI owns codec"));
9227                 VoiceChannelOff(a->AdvCodecPLCI);
9228                 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9229                 {
9230                         dbug(1, dprintf("remove temp codec PLCI"));
9231                         plci_remove(a->AdvCodecPLCI);
9232                         a->AdvCodecFLAG  = 0;
9233                         a->AdvCodecPLCI  = NULL;
9234                         a->AdvSignalAppl = NULL;
9235                 }
9236                 a->AdvSignalPLCI = NULL;
9237         }
9238 }
9239
9240 /* -------------------------------------------------------------------
9241    Ask for physical address of card on PCI bus
9242    ------------------------------------------------------------------- */
9243 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9244                                        IDI_SYNC_REQ *preq) {
9245         a->sdram_bar = 0;
9246         if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9247                 ENTITY *e = (ENTITY *)preq;
9248
9249                 e->user[0] = a->Id - 1;
9250                 preq->xdi_sdram_bar.info.bar    = 0;
9251                 preq->xdi_sdram_bar.Req         = 0;
9252                 preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9253
9254                 (*(a->request))(e);
9255
9256                 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9257                 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9258         }
9259 }
9260
9261 /* -------------------------------------------------------------------
9262    Ask XDI about extended features
9263    ------------------------------------------------------------------- */
9264 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9265         IDI_SYNC_REQ *preq;
9266         char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9267
9268         char features[4];
9269         preq = (IDI_SYNC_REQ *)&buffer[0];
9270
9271         if (!diva_xdi_extended_features) {
9272                 ENTITY *e = (ENTITY *)preq;
9273                 diva_xdi_extended_features |= 0x80000000;
9274
9275                 e->user[0] = a->Id - 1;
9276                 preq->xdi_extended_features.Req = 0;
9277                 preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9278                 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9279                 preq->xdi_extended_features.info.features = &features[0];
9280
9281                 (*(a->request))(e);
9282
9283                 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9284                         /*
9285                           Check features located in the byte '0'
9286                         */
9287                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9288                                 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9289                         }
9290                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9291                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9292                                 dbug(1, dprintf("XDI provides RxDMA"));
9293                         }
9294                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9295                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9296                         }
9297                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9298                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9299                                 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9300                         }
9301
9302                 }
9303         }
9304
9305         diva_ask_for_xdi_sdram_bar(a, preq);
9306 }
9307
9308 /*------------------------------------------------------------------*/
9309 /* automatic law                                                    */
9310 /*------------------------------------------------------------------*/
9311 /* called from OS specific part after init time to get the Law              */
9312 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9313 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9314 {
9315         word j;
9316         PLCI *splci;
9317
9318         if (a->automatic_law) {
9319                 return;
9320         }
9321         if ((j = get_plci(a))) {
9322                 diva_get_extended_adapter_features(a);
9323                 splci = &a->plci[j - 1];
9324                 a->automatic_lawPLCI = splci;
9325                 a->automatic_law = 1;
9326                 add_p(splci, CAI, "\x01\x80");
9327                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9328                 splci->internal_command = USELAW_REQ;
9329                 splci->command = 0;
9330                 splci->number = 0;
9331                 sig_req(splci, ASSIGN, DSIG_ID);
9332                 send_req(splci);
9333         }
9334 }
9335
9336 /* called from OS specific part if an application sends an Capi20Release */
9337 word CapiRelease(word Id)
9338 {
9339         word i, j, appls_found;
9340         PLCI *plci;
9341         APPL   *this;
9342         DIVA_CAPI_ADAPTER *a;
9343
9344         if (!Id)
9345         {
9346                 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9347                 return (_WRONG_APPL_ID);
9348         }
9349
9350         this = &application[Id - 1];               /* get application pointer */
9351
9352         for (i = 0, appls_found = 0; i < max_appl; i++)
9353         {
9354                 if (application[i].Id)       /* an application has been found        */
9355                 {
9356                         appls_found++;
9357                 }
9358         }
9359
9360         for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9361         {
9362                 a = &adapter[i];
9363                 if (a->request)
9364                 {
9365                         a->Info_Mask[Id - 1] = 0;
9366                         a->CIP_Mask[Id - 1] = 0;
9367                         a->Notification_Mask[Id - 1] = 0;
9368                         a->codec_listen[Id - 1] = NULL;
9369                         a->requested_options_table[Id - 1] = 0;
9370                         for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9371                         {                                      /* with this application   */
9372                                 plci = &a->plci[j];
9373                                 if (plci->Id)                         /* if plci owns no application */
9374                                 {                                    /* it may be not jet connected */
9375                                         if (plci->State == INC_CON_PENDING
9376                                             || plci->State == INC_CON_ALERT)
9377                                         {
9378                                                 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9379                                                 {
9380                                                         clear_c_ind_mask_bit(plci, (word)(Id - 1));
9381                                                         if (c_ind_mask_empty(plci))
9382                                                         {
9383                                                                 sig_req(plci, HANGUP, 0);
9384                                                                 send_req(plci);
9385                                                                 plci->State = OUTG_DIS_PENDING;
9386                                                         }
9387                                                 }
9388                                         }
9389                                         if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9390                                         {
9391                                                 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9392                                                 if (c_ind_mask_empty(plci))
9393                                                 {
9394                                                         if (!plci->appl)
9395                                                         {
9396                                                                 plci_remove(plci);
9397                                                                 plci->State = IDLE;
9398                                                         }
9399                                                 }
9400                                         }
9401                                         if (plci->appl == this)
9402                                         {
9403                                                 plci->appl = NULL;
9404                                                 plci_remove(plci);
9405                                                 plci->State = IDLE;
9406                                         }
9407                                 }
9408                         }
9409                         listen_check(a);
9410
9411                         if (a->flag_dynamic_l1_down)
9412                         {
9413                                 if (appls_found == 1)            /* last application does a capi release */
9414                                 {
9415                                         if ((j = get_plci(a)))
9416                                         {
9417                                                 plci = &a->plci[j - 1];
9418                                                 plci->command = 0;
9419                                                 add_p(plci, OAD, "\x01\xfd");
9420                                                 add_p(plci, CAI, "\x01\x80");
9421                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9422                                                 add_p(plci, SHIFT | 6, NULL);
9423                                                 add_p(plci, SIN, "\x02\x00\x00");
9424                                                 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9425                                                 sig_req(plci, ASSIGN, DSIG_ID);
9426                                                 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9427                                                 sig_req(plci, SIG_CTRL, 0);
9428                                                 send_req(plci);
9429                                         }
9430                                 }
9431                         }
9432                         if (a->AdvSignalAppl == this)
9433                         {
9434                                 this->NullCREnable = false;
9435                                 if (a->AdvCodecPLCI)
9436                                 {
9437                                         plci_remove(a->AdvCodecPLCI);
9438                                         a->AdvCodecPLCI->tel = 0;
9439                                         a->AdvCodecPLCI->adv_nl = 0;
9440                                 }
9441                                 a->AdvSignalAppl = NULL;
9442                                 a->AdvSignalPLCI = NULL;
9443                                 a->AdvCodecFLAG = 0;
9444                                 a->AdvCodecPLCI = NULL;
9445                         }
9446                 }
9447         }
9448
9449         this->Id = 0;
9450
9451         return GOOD;
9452 }
9453
9454 static word plci_remove_check(PLCI *plci)
9455 {
9456         if (!plci) return true;
9457         if (!plci->NL.Id && c_ind_mask_empty(plci))
9458         {
9459                 if (plci->Sig.Id == 0xff)
9460                         plci->Sig.Id = 0;
9461                 if (!plci->Sig.Id)
9462                 {
9463                         dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9464                         dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9465                         if (plci->Id)
9466                         {
9467                                 CodecIdCheck(plci->adapter, plci);
9468                                 clear_b1_config(plci);
9469                                 ncci_remove(plci, 0, false);
9470                                 plci_free_msg_in_queue(plci);
9471                                 channel_flow_control_remove(plci);
9472                                 plci->Id = 0;
9473                                 plci->State = IDLE;
9474                                 plci->channels = 0;
9475                                 plci->appl = NULL;
9476                                 plci->notifiedcall = 0;
9477                         }
9478                         listen_check(plci->adapter);
9479                         return true;
9480                 }
9481         }
9482         return false;
9483 }
9484
9485
9486 /*------------------------------------------------------------------*/
9487
9488 static byte plci_nl_busy(PLCI *plci)
9489 {
9490         /* only applicable for non-multiplexed protocols */
9491         return (plci->nl_req
9492                 || (plci->ncci_ring_list
9493                     && plci->adapter->ncci_ch[plci->ncci_ring_list]
9494                     && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9495 }
9496
9497
9498 /*------------------------------------------------------------------*/
9499 /* DTMF facilities                                                  */
9500 /*------------------------------------------------------------------*/
9501
9502
9503 static struct
9504 {
9505         byte send_mask;
9506         byte listen_mask;
9507         byte character;
9508         byte code;
9509 } dtmf_digit_map[] =
9510 {
9511         { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9512         { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9513         { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9514         { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9515         { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9516         { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9517         { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9518         { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9519         { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9520         { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9521         { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9522         { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9523         { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9524         { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9525         { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9526         { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9527         { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9528         { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9529         { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9530         { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9531
9532         { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9533         { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9534         { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9535         { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9536         { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9537         { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9538         { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9539         { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9540         { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9541         { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9542         { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9543         { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9544         { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9545         { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9546         { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9547         { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9548         { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9549         { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9550         { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9551         { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9552         { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9553         { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9554         { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9555         { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9556         { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9557         { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9558         { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9559         { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9560         { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9561         { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9562         { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9563         { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9564         { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9565         { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9566         { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9567         { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9568         { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9569         { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9570         { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9571         { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9572         { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9573         { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9574         { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9575         { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9576         { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9577         { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9578         { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9579         { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9580         { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9581         { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9582         { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9583         { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9584
9585 };
9586
9587 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588
9589
9590 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9591 {
9592         word min_digit_duration, min_gap_duration;
9593
9594         dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9595                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9596                         (char *)(FILE_), __LINE__, enable_mask));
9597
9598         if (enable_mask != 0)
9599         {
9600                 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9601                 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9602                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9603                 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9604                 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9605                 plci->NData[0].PLength = 5;
9606
9607                 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9608                 plci->NData[0].PLength += 2;
9609                 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9610
9611         }
9612         else
9613         {
9614                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9615                 plci->NData[0].PLength = 1;
9616
9617                 capidtmf_recv_disable(&(plci->capidtmf_state));
9618
9619         }
9620         plci->NData[0].P = plci->internal_req_buffer;
9621         plci->NL.X = plci->NData;
9622         plci->NL.ReqCh = 0;
9623         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9624         plci->adapter->request(&plci->NL);
9625 }
9626
9627
9628 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9629 {
9630         word w, i;
9631
9632         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9633                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9634                         (char *)(FILE_), __LINE__, digit_count));
9635
9636         plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9637         w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9638         PUT_WORD(&plci->internal_req_buffer[1], w);
9639         w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9640         PUT_WORD(&plci->internal_req_buffer[3], w);
9641         for (i = 0; i < digit_count; i++)
9642         {
9643                 w = 0;
9644                 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9645                        && (digit_buffer[i] != dtmf_digit_map[w].character))
9646                 {
9647                         w++;
9648                 }
9649                 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9650                         dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9651         }
9652         plci->NData[0].PLength = 5 + digit_count;
9653         plci->NData[0].P = plci->internal_req_buffer;
9654         plci->NL.X = plci->NData;
9655         plci->NL.ReqCh = 0;
9656         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9657         plci->adapter->request(&plci->NL);
9658 }
9659
9660
9661 static void dtmf_rec_clear_config(PLCI *plci)
9662 {
9663
9664         dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9665                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9666                         (char *)(FILE_), __LINE__));
9667
9668         plci->dtmf_rec_active = 0;
9669         plci->dtmf_rec_pulse_ms = 0;
9670         plci->dtmf_rec_pause_ms = 0;
9671
9672         capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9673
9674 }
9675
9676
9677 static void dtmf_send_clear_config(PLCI *plci)
9678 {
9679
9680         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9681                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9682                         (char *)(FILE_), __LINE__));
9683
9684         plci->dtmf_send_requests = 0;
9685         plci->dtmf_send_pulse_ms = 0;
9686         plci->dtmf_send_pause_ms = 0;
9687 }
9688
9689
9690 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9691 {
9692
9693         dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9694                         UnMapId(Id), (char *)(FILE_), __LINE__));
9695
9696         while (plci->dtmf_send_requests != 0)
9697                 dtmf_confirmation(Id, plci);
9698 }
9699
9700
9701 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9702 {
9703
9704         dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9705                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9706
9707         return (GOOD);
9708 }
9709
9710
9711 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9712 {
9713         word Info;
9714
9715         dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9716                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9717
9718         Info = GOOD;
9719         if (plci->B1_facilities & B1_FACILITY_DTMFR)
9720         {
9721                 switch (plci->adjust_b_state)
9722                 {
9723                 case ADJUST_B_RESTORE_DTMF_1:
9724                         plci->internal_command = plci->adjust_b_command;
9725                         if (plci_nl_busy(plci))
9726                         {
9727                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9728                                 break;
9729                         }
9730                         dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9731                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9732                         break;
9733                 case ADJUST_B_RESTORE_DTMF_2:
9734                         if ((Rc != OK) && (Rc != OK_FC))
9735                         {
9736                                 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9737                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9738                                 Info = _WRONG_STATE;
9739                                 break;
9740                         }
9741                         break;
9742                 }
9743         }
9744         return (Info);
9745 }
9746
9747
9748 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9749 {
9750         word internal_command, Info;
9751         byte mask;
9752         byte result[4];
9753
9754         dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9755                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9756                         plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9757                         plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9758
9759         Info = GOOD;
9760         result[0] = 2;
9761         PUT_WORD(&result[1], DTMF_SUCCESS);
9762         internal_command = plci->internal_command;
9763         plci->internal_command = 0;
9764         mask = 0x01;
9765         switch (plci->dtmf_cmd)
9766         {
9767
9768         case DTMF_LISTEN_TONE_START:
9769                 mask <<= 1;
9770         case DTMF_LISTEN_MF_START:
9771                 mask <<= 1;
9772
9773         case DTMF_LISTEN_START:
9774                 switch (internal_command)
9775                 {
9776                 default:
9777                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9778                                                                   B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9779                 case DTMF_COMMAND_1:
9780                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9781                         {
9782                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9783                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9784                                 Info = _FACILITY_NOT_SUPPORTED;
9785                                 break;
9786                         }
9787                         if (plci->internal_command)
9788                                 return;
9789                 case DTMF_COMMAND_2:
9790                         if (plci_nl_busy(plci))
9791                         {
9792                                 plci->internal_command = DTMF_COMMAND_2;
9793                                 return;
9794                         }
9795                         plci->internal_command = DTMF_COMMAND_3;
9796                         dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9797                         return;
9798                 case DTMF_COMMAND_3:
9799                         if ((Rc != OK) && (Rc != OK_FC))
9800                         {
9801                                 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9802                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9803                                 Info = _FACILITY_NOT_SUPPORTED;
9804                                 break;
9805                         }
9806
9807                         plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9808
9809                         plci->dtmf_rec_active |= mask;
9810                         break;
9811                 }
9812                 break;
9813
9814
9815         case DTMF_LISTEN_TONE_STOP:
9816                 mask <<= 1;
9817         case DTMF_LISTEN_MF_STOP:
9818                 mask <<= 1;
9819
9820         case DTMF_LISTEN_STOP:
9821                 switch (internal_command)
9822                 {
9823                 default:
9824                         plci->dtmf_rec_active &= ~mask;
9825                         if (plci->dtmf_rec_active)
9826                                 break;
9827 /*
9828   case DTMF_COMMAND_1:
9829   if (plci->dtmf_rec_active)
9830   {
9831   if (plci_nl_busy (plci))
9832   {
9833   plci->internal_command = DTMF_COMMAND_1;
9834   return;
9835   }
9836   plci->dtmf_rec_active &= ~mask;
9837   plci->internal_command = DTMF_COMMAND_2;
9838   dtmf_enable_receiver (plci, false);
9839   return;
9840   }
9841   Rc = OK;
9842   case DTMF_COMMAND_2:
9843   if ((Rc != OK) && (Rc != OK_FC))
9844   {
9845   dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9846   UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9847   Info = _FACILITY_NOT_SUPPORTED;
9848   break;
9849   }
9850 */
9851                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9852                                                                   ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9853                 case DTMF_COMMAND_3:
9854                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9855                         {
9856                                 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9857                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9858                                 Info = _FACILITY_NOT_SUPPORTED;
9859                                 break;
9860                         }
9861                         if (plci->internal_command)
9862                                 return;
9863                         break;
9864                 }
9865                 break;
9866
9867
9868         case DTMF_SEND_TONE:
9869                 mask <<= 1;
9870         case DTMF_SEND_MF:
9871                 mask <<= 1;
9872
9873         case DTMF_DIGITS_SEND:
9874                 switch (internal_command)
9875                 {
9876                 default:
9877                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9878                                                                   ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9879                                            DTMF_COMMAND_1);
9880                 case DTMF_COMMAND_1:
9881                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9882                         {
9883                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9884                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9885                                 Info = _FACILITY_NOT_SUPPORTED;
9886                                 break;
9887                         }
9888                         if (plci->internal_command)
9889                                 return;
9890                 case DTMF_COMMAND_2:
9891                         if (plci_nl_busy(plci))
9892                         {
9893                                 plci->internal_command = DTMF_COMMAND_2;
9894                                 return;
9895                         }
9896                         plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9897                         plci->internal_command = DTMF_COMMAND_3;
9898                         dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9899                         return;
9900                 case DTMF_COMMAND_3:
9901                         if ((Rc != OK) && (Rc != OK_FC))
9902                         {
9903                                 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9904                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9905                                 if (plci->dtmf_send_requests != 0)
9906                                         (plci->dtmf_send_requests)--;
9907                                 Info = _FACILITY_NOT_SUPPORTED;
9908                                 break;
9909                         }
9910                         return;
9911                 }
9912                 break;
9913         }
9914         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9915               "wws", Info, SELECTOR_DTMF, result);
9916 }
9917
9918
9919 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9920 {
9921         word Info;
9922         word i, j;
9923         byte mask;
9924         API_PARSE dtmf_parms[5];
9925         byte result[40];
9926
9927         dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9928                         UnMapId(Id), (char *)(FILE_), __LINE__));
9929
9930         Info = GOOD;
9931         result[0] = 2;
9932         PUT_WORD(&result[1], DTMF_SUCCESS);
9933         if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9934         {
9935                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9936                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9937                 Info = _FACILITY_NOT_SUPPORTED;
9938         }
9939         else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9940         {
9941                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9942                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9943                 Info = _WRONG_MESSAGE_FORMAT;
9944         }
9945
9946         else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947                  || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9948         {
9949                 if (!((a->requested_options_table[appl->Id - 1])
9950                       & (1L << PRIVATE_DTMF_TONE)))
9951                 {
9952                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9953                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9954                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9955                 }
9956                 else
9957                 {
9958                         for (i = 0; i < 32; i++)
9959                                 result[4 + i] = 0;
9960                         if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9961                         {
9962                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9963                                 {
9964                                         if (dtmf_digit_map[i].listen_mask != 0)
9965                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9966                                 }
9967                         }
9968                         else
9969                         {
9970                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9971                                 {
9972                                         if (dtmf_digit_map[i].send_mask != 0)
9973                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9974                                 }
9975                         }
9976                         result[0] = 3 + 32;
9977                         result[3] = 32;
9978                 }
9979         }
9980
9981         else if (plci == NULL)
9982         {
9983                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9984                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9985                 Info = _WRONG_IDENTIFIER;
9986         }
9987         else
9988         {
9989                 if (!plci->State
9990                     || !plci->NL.Id || plci->nl_remove_id)
9991                 {
9992                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9993                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9994                         Info = _WRONG_STATE;
9995                 }
9996                 else
9997                 {
9998                         plci->command = 0;
9999                         plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
10000                         mask = 0x01;
10001                         switch (plci->dtmf_cmd)
10002                         {
10003
10004                         case DTMF_LISTEN_TONE_START:
10005                         case DTMF_LISTEN_TONE_STOP:
10006                                 mask <<= 1;
10007                         case DTMF_LISTEN_MF_START:
10008                         case DTMF_LISTEN_MF_STOP:
10009                                 mask <<= 1;
10010                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10011                                       & (1L << PRIVATE_DTMF_TONE)))
10012                                 {
10013                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10014                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10015                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10016                                         break;
10017                                 }
10018
10019                         case DTMF_LISTEN_START:
10020                         case DTMF_LISTEN_STOP:
10021                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10022                                     && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10023                                 {
10024                                         dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10025                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10026                                         Info = _FACILITY_NOT_SUPPORTED;
10027                                         break;
10028                                 }
10029                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10030                                 {
10031                                         if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10032                                         {
10033                                                 plci->dtmf_rec_pulse_ms = 0;
10034                                                 plci->dtmf_rec_pause_ms = 0;
10035                                         }
10036                                         else
10037                                         {
10038                                                 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10039                                                 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10040                                         }
10041                                 }
10042                                 start_internal_command(Id, plci, dtmf_command);
10043                                 return (false);
10044
10045
10046                         case DTMF_SEND_TONE:
10047                                 mask <<= 1;
10048                         case DTMF_SEND_MF:
10049                                 mask <<= 1;
10050                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10051                                       & (1L << PRIVATE_DTMF_TONE)))
10052                                 {
10053                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10054                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10055                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10056                                         break;
10057                                 }
10058
10059                         case DTMF_DIGITS_SEND:
10060                                 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10061                                 {
10062                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10063                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10064                                         Info = _WRONG_MESSAGE_FORMAT;
10065                                         break;
10066                                 }
10067                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10068                                 {
10069                                         plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10070                                         plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10071                                 }
10072                                 i = 0;
10073                                 j = 0;
10074                                 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10075                                 {
10076                                         j = 0;
10077                                         while ((j < DTMF_DIGIT_MAP_ENTRIES)
10078                                                && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10079                                                    || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10080                                         {
10081                                                 j++;
10082                                         }
10083                                         i++;
10084                                 }
10085                                 if (j == DTMF_DIGIT_MAP_ENTRIES)
10086                                 {
10087                                         dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10088                                                         UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10089                                         PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10090                                         break;
10091                                 }
10092                                 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10093                                 {
10094                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10095                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10096                                         Info = _WRONG_STATE;
10097                                         break;
10098                                 }
10099                                 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10100                                 start_internal_command(Id, plci, dtmf_command);
10101                                 return (false);
10102
10103                         default:
10104                                 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10105                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10106                                 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10107                         }
10108                 }
10109         }
10110         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10111               "wws", Info, SELECTOR_DTMF, result);
10112         return (false);
10113 }
10114
10115
10116 static void dtmf_confirmation(dword Id, PLCI *plci)
10117 {
10118         word i;
10119         byte result[4];
10120
10121         dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10122                         UnMapId(Id), (char *)(FILE_), __LINE__));
10123
10124         result[0] = 2;
10125         PUT_WORD(&result[1], DTMF_SUCCESS);
10126         if (plci->dtmf_send_requests != 0)
10127         {
10128                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10129                       "wws", GOOD, SELECTOR_DTMF, result);
10130                 (plci->dtmf_send_requests)--;
10131                 for (i = 0; i < plci->dtmf_send_requests; i++)
10132                         plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10133         }
10134 }
10135
10136
10137 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10138 {
10139         word i, j, n;
10140
10141         dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10142                         UnMapId(Id), (char *)(FILE_), __LINE__));
10143
10144         n = 0;
10145         for (i = 1; i < length; i++)
10146         {
10147                 j = 0;
10148                 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10149                        && ((msg[i] != dtmf_digit_map[j].code)
10150                            || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10151                 {
10152                         j++;
10153                 }
10154                 if (j < DTMF_DIGIT_MAP_ENTRIES)
10155                 {
10156
10157                         if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10158                             && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10159                             && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10160                         {
10161                                 if (n + 1 == i)
10162                                 {
10163                                         for (i = length; i > n + 1; i--)
10164                                                 msg[i] = msg[i - 1];
10165                                         length++;
10166                                         i++;
10167                                 }
10168                                 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10169                         }
10170                         plci->tone_last_indication_code = dtmf_digit_map[j].character;
10171
10172                         msg[++n] = dtmf_digit_map[j].character;
10173                 }
10174         }
10175         if (n != 0)
10176         {
10177                 msg[0] = (byte) n;
10178                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10179         }
10180 }
10181
10182
10183 /*------------------------------------------------------------------*/
10184 /* DTMF parameters                                                  */
10185 /*------------------------------------------------------------------*/
10186
10187 static void dtmf_parameter_write(PLCI *plci)
10188 {
10189         word i;
10190         byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10191
10192         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10193                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10194                         (char *)(FILE_), __LINE__));
10195
10196         parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10197         parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10198         for (i = 0; i < plci->dtmf_parameter_length; i++)
10199                 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10200         add_p(plci, FTY, parameter_buffer);
10201         sig_req(plci, TEL_CTRL, 0);
10202         send_req(plci);
10203 }
10204
10205
10206 static void dtmf_parameter_clear_config(PLCI *plci)
10207 {
10208
10209         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10210                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10211                         (char *)(FILE_), __LINE__));
10212
10213         plci->dtmf_parameter_length = 0;
10214 }
10215
10216
10217 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10218 {
10219
10220         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10221                         UnMapId(Id), (char *)(FILE_), __LINE__));
10222
10223 }
10224
10225
10226 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10227 {
10228
10229         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10230                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231
10232         return (GOOD);
10233 }
10234
10235
10236 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10237 {
10238         word Info;
10239
10240         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10241                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10242
10243         Info = GOOD;
10244         if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10245             && (plci->dtmf_parameter_length != 0))
10246         {
10247                 switch (plci->adjust_b_state)
10248                 {
10249                 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10250                         plci->internal_command = plci->adjust_b_command;
10251                         if (plci->sig_req)
10252                         {
10253                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10254                                 break;
10255                         }
10256                         dtmf_parameter_write(plci);
10257                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10258                         break;
10259                 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10260                         if ((Rc != OK) && (Rc != OK_FC))
10261                         {
10262                                 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10263                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10264                                 Info = _WRONG_STATE;
10265                                 break;
10266                         }
10267                         break;
10268                 }
10269         }
10270         return (Info);
10271 }
10272
10273
10274 /*------------------------------------------------------------------*/
10275 /* Line interconnect facilities                                     */
10276 /*------------------------------------------------------------------*/
10277
10278
10279 LI_CONFIG   *li_config_table;
10280 word li_total_channels;
10281
10282
10283 /*------------------------------------------------------------------*/
10284 /* translate a CHI information element to a channel number          */
10285 /* returns 0xff - any channel                                       */
10286 /*         0xfe - chi wrong coding                                  */
10287 /*         0xfd - D-channel                                         */
10288 /*         0x00 - no channel                                        */
10289 /*         else channel number / PRI: timeslot                      */
10290 /* if channels is provided we accept more than one channel.         */
10291 /*------------------------------------------------------------------*/
10292
10293 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10294 {
10295         int p;
10296         int i;
10297         dword map;
10298         byte excl;
10299         byte ofs;
10300         byte ch;
10301
10302         if (pchannelmap) *pchannelmap = 0;
10303         if (!chi[0]) return 0xff;
10304         excl = 0;
10305
10306         if (chi[1] & 0x20) {
10307                 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10308                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10309                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10310                 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10311                 if (chi[1] & 0x08) excl = 0x40;
10312
10313                 /* int. id present */
10314                 if (chi[1] & 0x40) {
10315                         p = i + 1;
10316                         for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10317                         if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10318                 }
10319
10320                 /* coding standard, Number/Map, Channel Type */
10321                 p = i + 1;
10322                 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10323                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10324                 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10325
10326                 /* Number/Map */
10327                 if (chi[p] & 0x10) {
10328
10329                         /* map */
10330                         if ((chi[0] - p) == 4) ofs = 0;
10331                         else if ((chi[0] - p) == 3) ofs = 1;
10332                         else return 0xfe;
10333                         ch = 0;
10334                         map = 0;
10335                         for (i = 0; i < 4 && p < chi[0]; i++) {
10336                                 p++;
10337                                 ch += 8;
10338                                 map <<= 8;
10339                                 if (chi[p]) {
10340                                         for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10341                                         map |= chi[p];
10342                                 }
10343                         }
10344                         ch += ofs;
10345                         map <<= ofs;
10346                 }
10347                 else {
10348
10349                         /* number */
10350                         p = i + 1;
10351                         ch = chi[p] & 0x3f;
10352                         if (pchannelmap) {
10353                                 if ((byte)(chi[0] - p) > 30) return 0xfe;
10354                                 map = 0;
10355                                 for (i = p; i <= chi[0]; i++) {
10356                                         if ((chi[i] & 0x7f) > 31) return 0xfe;
10357                                         map |= (1L << (chi[i] & 0x7f));
10358                                 }
10359                         }
10360                         else {
10361                                 if (p != chi[0]) return 0xfe;
10362                                 if (ch > 31) return 0xfe;
10363                                 map = (1L << ch);
10364                         }
10365                         if (chi[p] & 0x40) return 0xfe;
10366                 }
10367                 if (pchannelmap) *pchannelmap = map;
10368                 else if (map != ((dword)(1L << ch))) return 0xfe;
10369                 return (byte)(excl | ch);
10370         }
10371         else {  /* not PRI */
10372                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10373                 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10374                 if (chi[1] & 0x08) excl = 0x40;
10375
10376                 switch (chi[1] | 0x98) {
10377                 case 0x98: return 0;
10378                 case 0x99:
10379                         if (pchannelmap) *pchannelmap = 2;
10380                         return excl | 1;
10381                 case 0x9a:
10382                         if (pchannelmap) *pchannelmap = 4;
10383                         return excl | 2;
10384                 case 0x9b: return 0xff;
10385                 case 0x9c: return 0xfd; /* d-ch */
10386                 default: return 0xfe;
10387                 }
10388         }
10389 }
10390
10391
10392 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10393 {
10394         DIVA_CAPI_ADAPTER *a;
10395         PLCI *splci;
10396         byte old_id;
10397
10398         a = plci->adapter;
10399         old_id = plci->li_bchannel_id;
10400         if (a->li_pri)
10401         {
10402                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10403                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10404                 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10405                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10406                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10407         }
10408         else
10409         {
10410                 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10411                 {
10412                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10413                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10414                         plci->li_bchannel_id = bchannel_id & 0x03;
10415                         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10416                         {
10417                                 splci = a->AdvSignalPLCI;
10418                                 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10419                                 {
10420                                         if ((splci->li_bchannel_id != 0)
10421                                             && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10422                                         {
10423                                                 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10424                                         }
10425                                         splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10426                                         li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10427                                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10428                                                         (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10429                                                         (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10430                                 }
10431                         }
10432                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10433                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10434                 }
10435         }
10436         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10437             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10438         {
10439                 mixer_clear_config(plci);
10440         }
10441         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10442                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10443                         (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10444 }
10445
10446
10447 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10448 {
10449         DIVA_CAPI_ADAPTER *a;
10450         PLCI *splci;
10451         byte ch, old_id;
10452
10453         a = plci->adapter;
10454         old_id = plci->li_bchannel_id;
10455         ch = chi_to_channel(chi, NULL);
10456         if (!(ch & 0x80))
10457         {
10458                 if (a->li_pri)
10459                 {
10460                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10461                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10462                         plci->li_bchannel_id = (ch & 0x1f) + 1;
10463                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10464                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10465                 }
10466                 else
10467                 {
10468                         if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10469                         {
10470                                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10471                                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10472                                 plci->li_bchannel_id = ch & 0x1f;
10473                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10474                                 {
10475                                         splci = a->AdvSignalPLCI;
10476                                         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10477                                         {
10478                                                 if ((splci->li_bchannel_id != 0)
10479                                                     && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10480                                                 {
10481                                                         li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10482                                                 }
10483                                                 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10484                                                 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10485                                                 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10486                                                                 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10487                                                                 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10488                                         }
10489                                 }
10490                                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10491                                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10492                         }
10493                 }
10494         }
10495         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10496             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10497         {
10498                 mixer_clear_config(plci);
10499         }
10500         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10501                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10502                         (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10503 }
10504
10505
10506 #define MIXER_MAX_DUMP_CHANNELS 34
10507
10508 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10509 {
10510         static char hex_digit_table[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
10511         word n, i, j;
10512         char *p;
10513         char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10514
10515         dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10516                         (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10517
10518         for (i = 0; i < li_total_channels; i++)
10519         {
10520                 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10521                 if (li_config_table[i].chflags != 0)
10522                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10523                 else
10524                 {
10525                         for (j = 0; j < li_total_channels; j++)
10526                         {
10527                                 if (((li_config_table[i].flag_table[j]) != 0)
10528                                     || ((li_config_table[j].flag_table[i]) != 0))
10529                                 {
10530                                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10531                                 }
10532                                 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10533                                     || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10534                                 {
10535                                         li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10536                                 }
10537                         }
10538                 }
10539         }
10540         for (i = 0; i < li_total_channels; i++)
10541         {
10542                 for (j = 0; j < li_total_channels; j++)
10543                 {
10544                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10545                         if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10546                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10547                 }
10548         }
10549         for (n = 0; n < li_total_channels; n++)
10550         {
10551                 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10552                 {
10553                         for (i = 0; i < li_total_channels; i++)
10554                         {
10555                                 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10556                                 {
10557                                         for (j = 0; j < li_total_channels; j++)
10558                                         {
10559                                                 li_config_table[i].coef_table[j] |=
10560                                                         li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10561                                         }
10562                                 }
10563                         }
10564                 }
10565         }
10566         for (i = 0; i < li_total_channels; i++)
10567         {
10568                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10569                 {
10570                         li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10571                         for (j = 0; j < li_total_channels; j++)
10572                         {
10573                                 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10574                                         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10575                         }
10576                         if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10577                                 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10578                 }
10579         }
10580         for (i = 0; i < li_total_channels; i++)
10581         {
10582                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10583                 {
10584                         for (j = 0; j < li_total_channels; j++)
10585                         {
10586                                 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10588                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10589                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10590                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10591                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10592                                 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10593                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10594                         }
10595                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10596                         {
10597                                 for (j = 0; j < li_total_channels; j++)
10598                                 {
10599                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10600                                         {
10601                                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10602                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10603                                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10604                                         }
10605                                 }
10606                         }
10607                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10608                         {
10609                                 for (j = 0; j < li_total_channels; j++)
10610                                 {
10611                                         if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10612                                                 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10613                                 }
10614                         }
10615                         if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10616                         {
10617                                 for (j = 0; j < li_total_channels; j++)
10618                                 {
10619                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10620                                         {
10621                                                 for (n = 0; n < li_total_channels; n++)
10622                                                 {
10623                                                         if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10624                                                         {
10625                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10626                                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10627                                                                 {
10628                                                                         li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10629                                                                         if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630                                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10631                                                                 }
10632                                                                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10633                                                                         li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10634                                                         }
10635                                                 }
10636                                         }
10637                                 }
10638                         }
10639                 }
10640         }
10641         for (i = 0; i < li_total_channels; i++)
10642         {
10643                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10644                 {
10645                         if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10646                                 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10647                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10648                                 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10650                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651                         for (j = 0; j < li_total_channels; j++)
10652                         {
10653                                 if ((li_config_table[i].flag_table[j] &
10654                                      (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10655                                     || (li_config_table[j].flag_table[i] &
10656                                         (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10657                                 {
10658                                         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10659                                 }
10660                                 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10661                                         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10662                                 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10663                                         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10664                         }
10665                         if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10666                         {
10667                                 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10668                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10669                         }
10670                 }
10671         }
10672         for (i = 0; i < li_total_channels; i++)
10673         {
10674                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10675                 {
10676                         j = 0;
10677                         while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10678                                 j++;
10679                         if (j < li_total_channels)
10680                         {
10681                                 for (j = 0; j < li_total_channels; j++)
10682                                 {
10683                                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10684                                         if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10685                                                 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10686                                 }
10687                         }
10688                 }
10689         }
10690         n = li_total_channels;
10691         if (n > MIXER_MAX_DUMP_CHANNELS)
10692                 n = MIXER_MAX_DUMP_CHANNELS;
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].curchnl >> 4];
10699                 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10700         }
10701         *p = '\0';
10702         dbug(1, dprintf("[%06lx] CURRENT %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].channel >> 4];
10710                 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10711         }
10712         *p = '\0';
10713         dbug(1, dprintf("[%06lx] CHANNEL %s",
10714                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10715         p = hex_line;
10716         for (j = 0; j < n; j++)
10717         {
10718                 if ((j & 0x7) == 0)
10719                         *(p++) = ' ';
10720                 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10721                 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10722         }
10723         *p = '\0';
10724         dbug(1, dprintf("[%06lx] CHFLAG  %s",
10725                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10726         for (i = 0; i < n; i++)
10727         {
10728                 p = hex_line;
10729                 for (j = 0; j < n; j++)
10730                 {
10731                         if ((j & 0x7) == 0)
10732                                 *(p++) = ' ';
10733                         *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10734                         *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10735                 }
10736                 *p = '\0';
10737                 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10738                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10739         }
10740         for (i = 0; i < n; i++)
10741         {
10742                 p = hex_line;
10743                 for (j = 0; j < n; j++)
10744                 {
10745                         if ((j & 0x7) == 0)
10746                                 *(p++) = ' ';
10747                         *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10748                         *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10749                 }
10750                 *p = '\0';
10751                 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10752                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10753         }
10754 }
10755
10756
10757 static struct
10758 {
10759         byte mask;
10760         byte line_flags;
10761 } mixer_write_prog_pri[] =
10762 {
10763         { LI_COEF_CH_CH, 0 },
10764         { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10765         { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10766         { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10767 };
10768
10769 static struct
10770 {
10771         byte from_ch;
10772         byte to_ch;
10773         byte mask;
10774         byte xconnect_override;
10775 } mixer_write_prog_bri[] =
10776 {
10777         { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10778         { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10779         { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10780         { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10781         { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10782         { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10783         { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10784         { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10785         { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10786         { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10787         { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10788         { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10789         { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10790         { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10791         { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10792         { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10793         { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10794         { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10795         { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10796         { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10797         { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10798         { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10799         { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10800         { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10801         { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10802         { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10803         { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10804         { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10805         { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10806         { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10807         { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10808         { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10809         { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10810         { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10811         { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10812         { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10813 };
10814
10815 static byte mixer_swapped_index_bri[] =
10816 {
10817         18,  /* B      to B      */
10818         19,  /* Alt B  to B      */
10819         20,  /* PC     to B      */
10820         21,  /* Alt PC to B      */
10821         22,  /* IC     to B      */
10822         23,  /* Alt IC to B      */
10823         24,  /* B      to PC     */
10824         25,  /* Alt B  to PC     */
10825         26,  /* PC     to PC     */
10826         27,  /* Alt PC to PC     */
10827         28,  /* IC     to PC     */
10828         29,  /* Alt IC to PC     */
10829         30,  /* B      to IC     */
10830         31,  /* Alt B  to IC     */
10831         32,  /* PC     to IC     */
10832         33,  /* Alt PC to IC     */
10833         34,  /* IC     to IC     */
10834         35,  /* Alt IC to IC     */
10835         0,   /* Alt B  to Alt B  */
10836         1,   /* B      to Alt B  */
10837         2,   /* Alt PC to Alt B  */
10838         3,   /* PC     to Alt B  */
10839         4,   /* Alt IC to Alt B  */
10840         5,   /* IC     to Alt B  */
10841         6,   /* Alt B  to Alt PC */
10842         7,   /* B      to Alt PC */
10843         8,   /* Alt PC to Alt PC */
10844         9,   /* PC     to Alt PC */
10845         10,  /* Alt IC to Alt PC */
10846         11,  /* IC     to Alt PC */
10847         12,  /* Alt B  to Alt IC */
10848         13,  /* B      to Alt IC */
10849         14,  /* Alt PC to Alt IC */
10850         15,  /* PC     to Alt IC */
10851         16,  /* Alt IC to Alt IC */
10852         17   /* IC     to Alt IC */
10853 };
10854
10855 static struct
10856 {
10857         byte mask;
10858         byte from_pc;
10859         byte to_pc;
10860 } xconnect_write_prog[] =
10861 {
10862         { LI_COEF_CH_CH, false, false },
10863         { LI_COEF_CH_PC, false, true },
10864         { LI_COEF_PC_CH, true, false },
10865         { LI_COEF_PC_PC, true, true }
10866 };
10867
10868
10869 static void xconnect_query_addresses(PLCI *plci)
10870 {
10871         DIVA_CAPI_ADAPTER *a;
10872         word w, ch;
10873         byte *p;
10874
10875         dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10876                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10877                         (char *)(FILE_), __LINE__));
10878
10879         a = plci->adapter;
10880         if (a->li_pri && ((plci->li_bchannel_id == 0)
10881                           || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10882         {
10883                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10884                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10885                                 (char *)(FILE_), __LINE__));
10886                 return;
10887         }
10888         p = plci->internal_req_buffer;
10889         ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10890         *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10891         w = ch;
10892         *(p++) = (byte) w;
10893         *(p++) = (byte)(w >> 8);
10894         w = ch | XCONNECT_CHANNEL_PORT_PC;
10895         *(p++) = (byte) w;
10896         *(p++) = (byte)(w >> 8);
10897         plci->NData[0].P = plci->internal_req_buffer;
10898         plci->NData[0].PLength = p - plci->internal_req_buffer;
10899         plci->NL.X = plci->NData;
10900         plci->NL.ReqCh = 0;
10901         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10902         plci->adapter->request(&plci->NL);
10903 }
10904
10905
10906 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10907 {
10908
10909         dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10910                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10911                         (char *)(FILE_), __LINE__, internal_command));
10912
10913         plci->li_write_command = internal_command;
10914         plci->li_write_channel = 0;
10915 }
10916
10917
10918 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10919 {
10920         DIVA_CAPI_ADAPTER *a;
10921         word w, n, i, j, r, s, to_ch;
10922         dword d;
10923         byte *p;
10924         struct xconnect_transfer_address_s   *transfer_address;
10925         byte ch_map[MIXER_CHANNELS_BRI];
10926
10927         dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10928                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10929
10930         a = plci->adapter;
10931         if ((plci->li_bchannel_id == 0)
10932             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10933         {
10934                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10935                                 UnMapId(Id), (char *)(FILE_), __LINE__));
10936                 return (true);
10937         }
10938         i = a->li_base + (plci->li_bchannel_id - 1);
10939         j = plci->li_write_channel;
10940         p = plci->internal_req_buffer;
10941         if (j != 0)
10942         {
10943                 if ((Rc != OK) && (Rc != OK_FC))
10944                 {
10945                         dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10946                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10947                         return (false);
10948                 }
10949         }
10950         if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10951         {
10952                 r = 0;
10953                 s = 0;
10954                 if (j < li_total_channels)
10955                 {
10956                         if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10957                         {
10958                                 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10959                                      (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10960                                         ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10961                                          (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10962                         }
10963                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964                         while ((j < li_total_channels)
10965                                && ((r == 0)
10966                                    || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10967                                    || (!li_config_table[j].adapter->li_pri
10968                                        && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10969                                    || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10970                                         || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10971                                        && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10972                                            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10973                                    || ((li_config_table[j].adapter->li_base != a->li_base)
10974                                        && !(r & s &
10975                                             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10976                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10977                                             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10978                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10979                         {
10980                                 j++;
10981                                 if (j < li_total_channels)
10982                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10983                         }
10984                 }
10985                 if (j < li_total_channels)
10986                 {
10987                         plci->internal_command = plci->li_write_command;
10988                         if (plci_nl_busy(plci))
10989                                 return (true);
10990                         to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10991                         *(p++) = UDATA_REQUEST_XCONNECT_TO;
10992                         do
10993                         {
10994                                 if (li_config_table[j].adapter->li_base != a->li_base)
10995                                 {
10996                                         r &= s &
10997                                                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10998                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10999                                                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11000                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11001                                 }
11002                                 n = 0;
11003                                 do
11004                                 {
11005                                         if (r & xconnect_write_prog[n].mask)
11006                                         {
11007                                                 if (xconnect_write_prog[n].from_pc)
11008                                                         transfer_address = &(li_config_table[j].send_pc);
11009                                                 else
11010                                                         transfer_address = &(li_config_table[j].send_b);
11011                                                 d = transfer_address->card_address.low;
11012                                                 *(p++) = (byte) d;
11013                                                 *(p++) = (byte)(d >> 8);
11014                                                 *(p++) = (byte)(d >> 16);
11015                                                 *(p++) = (byte)(d >> 24);
11016                                                 d = transfer_address->card_address.high;
11017                                                 *(p++) = (byte) d;
11018                                                 *(p++) = (byte)(d >> 8);
11019                                                 *(p++) = (byte)(d >> 16);
11020                                                 *(p++) = (byte)(d >> 24);
11021                                                 d = transfer_address->offset;
11022                                                 *(p++) = (byte) d;
11023                                                 *(p++) = (byte)(d >> 8);
11024                                                 *(p++) = (byte)(d >> 16);
11025                                                 *(p++) = (byte)(d >> 24);
11026                                                 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11027                                                 *(p++) = (byte) w;
11028                                                 *(p++) = (byte)(w >> 8);
11029                                                 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11030                                                         (li_config_table[i].adapter->u_law ?
11031                                                          (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11032                                                          (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11033                                                 *(p++) = (byte) w;
11034                                                 *(p++) = (byte) 0;
11035                                                 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11036                                         }
11037                                         n++;
11038                                 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11039                                          && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11040                                 if (n == ARRAY_SIZE(xconnect_write_prog))
11041                                 {
11042                                         do
11043                                         {
11044                                                 j++;
11045                                                 if (j < li_total_channels)
11046                                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11047                                         } while ((j < li_total_channels)
11048                                                  && ((r == 0)
11049                                                      || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11050                                                      || (!li_config_table[j].adapter->li_pri
11051                                                          && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11052                                                      || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11053                                                           || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11054                                                          && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11055                                                              || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11056                                                      || ((li_config_table[j].adapter->li_base != a->li_base)
11057                                                          && !(r & s &
11058                                                               ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11059                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11060                                                               ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11061                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11062                                 }
11063                         } while ((j < li_total_channels)
11064                                  && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11065                 }
11066                 else if (j == li_total_channels)
11067                 {
11068                         plci->internal_command = plci->li_write_command;
11069                         if (plci_nl_busy(plci))
11070                                 return (true);
11071                         if (a->li_pri)
11072                         {
11073                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11074                                 w = 0;
11075                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11076                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11077                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11078                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11079                                 *(p++) = (byte) w;
11080                                 *(p++) = (byte)(w >> 8);
11081                         }
11082                         else
11083                         {
11084                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11085                                 w = 0;
11086                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11087                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11088                                 {
11089                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11090                                 }
11091                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11092                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11093                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11094                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11095                                 *(p++) = (byte) w;
11096                                 *(p++) = (byte)(w >> 8);
11097                                 for (j = 0; j < sizeof(ch_map); j += 2)
11098                                 {
11099                                         if (plci->li_bchannel_id == 2)
11100                                         {
11101                                                 ch_map[j] = (byte)(j + 1);
11102                                                 ch_map[j + 1] = (byte) j;
11103                                         }
11104                                         else
11105                                         {
11106                                                 ch_map[j] = (byte) j;
11107                                                 ch_map[j + 1] = (byte)(j + 1);
11108                                         }
11109                                 }
11110                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11111                                 {
11112                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11113                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11114                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11115                                         {
11116                                                 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11117                                                         mixer_write_prog_bri[n].xconnect_override :
11118                                                         ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11119                                                 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11120                                                 {
11121                                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11122                                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11123                                                 }
11124                                         }
11125                                         else
11126                                         {
11127                                                 *p = 0x00;
11128                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11129                                                 {
11130                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11131                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11132                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11133                                                 }
11134                                         }
11135                                         p++;
11136                                 }
11137                         }
11138                         j = li_total_channels + 1;
11139                 }
11140         }
11141         else
11142         {
11143                 if (j <= li_total_channels)
11144                 {
11145                         plci->internal_command = plci->li_write_command;
11146                         if (plci_nl_busy(plci))
11147                                 return (true);
11148                         if (j < a->li_base)
11149                                 j = a->li_base;
11150                         if (a->li_pri)
11151                         {
11152                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11153                                 w = 0;
11154                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11155                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11156                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11157                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11158                                 *(p++) = (byte) w;
11159                                 *(p++) = (byte)(w >> 8);
11160                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11161                                 {
11162                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11163                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11164                                         {
11165                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11166                                                 if (w & mixer_write_prog_pri[n].mask)
11167                                                 {
11168                                                         *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11169                                                         li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11170                                                 }
11171                                                 else
11172                                                         *(p++) = 0x00;
11173                                         }
11174                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11175                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11176                                         {
11177                                                 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11178                                                 if (w & mixer_write_prog_pri[n].mask)
11179                                                 {
11180                                                         *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11181                                                         li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11182                                                 }
11183                                                 else
11184                                                         *(p++) = 0x00;
11185                                         }
11186                                 }
11187                         }
11188                         else
11189                         {
11190                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11191                                 w = 0;
11192                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11193                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11194                                 {
11195                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11196                                 }
11197                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11198                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11199                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11200                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11201                                 *(p++) = (byte) w;
11202                                 *(p++) = (byte)(w >> 8);
11203                                 for (j = 0; j < sizeof(ch_map); j += 2)
11204                                 {
11205                                         if (plci->li_bchannel_id == 2)
11206                                         {
11207                                                 ch_map[j] = (byte)(j + 1);
11208                                                 ch_map[j + 1] = (byte) j;
11209                                         }
11210                                         else
11211                                         {
11212                                                 ch_map[j] = (byte) j;
11213                                                 ch_map[j + 1] = (byte)(j + 1);
11214                                         }
11215                                 }
11216                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11217                                 {
11218                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11219                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11220                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11221                                         {
11222                                                 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11223                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11224                                                 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11225                                         }
11226                                         else
11227                                         {
11228                                                 *p = 0x00;
11229                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11230                                                 {
11231                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11232                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11233                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11234                                                 }
11235                                         }
11236                                         p++;
11237                                 }
11238                         }
11239                         j = li_total_channels + 1;
11240                 }
11241         }
11242         plci->li_write_channel = j;
11243         if (p != plci->internal_req_buffer)
11244         {
11245                 plci->NData[0].P = plci->internal_req_buffer;
11246                 plci->NData[0].PLength = p - plci->internal_req_buffer;
11247                 plci->NL.X = plci->NData;
11248                 plci->NL.ReqCh = 0;
11249                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11250                 plci->adapter->request(&plci->NL);
11251         }
11252         return (true);
11253 }
11254
11255
11256 static void mixer_notify_update(PLCI *plci, byte others)
11257 {
11258         DIVA_CAPI_ADAPTER *a;
11259         word i, w;
11260         PLCI *notify_plci;
11261         byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11262
11263         dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11264                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11265                         (char *)(FILE_), __LINE__, others));
11266
11267         a = plci->adapter;
11268         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11269         {
11270                 if (others)
11271                         plci->li_notify_update = true;
11272                 i = 0;
11273                 do
11274                 {
11275                         notify_plci = NULL;
11276                         if (others)
11277                         {
11278                                 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11279                                         i++;
11280                                 if (i < li_total_channels)
11281                                         notify_plci = li_config_table[i++].plci;
11282                         }
11283                         else
11284                         {
11285                                 if ((plci->li_bchannel_id != 0)
11286                                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11287                                 {
11288                                         notify_plci = plci;
11289                                 }
11290                         }
11291                         if ((notify_plci != NULL)
11292                             && !notify_plci->li_notify_update
11293                             && (notify_plci->appl != NULL)
11294                             && (notify_plci->State)
11295                             && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11296                         {
11297                                 notify_plci->li_notify_update = true;
11298                                 ((CAPI_MSG *) msg)->header.length = 18;
11299                                 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11300                                 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11301                                 ((CAPI_MSG *) msg)->header.number = 0;
11302                                 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11303                                 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11304                                 ((CAPI_MSG *) msg)->header.ncci = 0;
11305                                 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11306                                 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11307                                 PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11308                                 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11309                                 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11310                                 if (w != _QUEUE_FULL)
11311                                 {
11312                                         if (w != 0)
11313                                         {
11314                                                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11315                                                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11316                                                                 (char *)(FILE_), __LINE__,
11317                                                                 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11318                                         }
11319                                         notify_plci->li_notify_update = false;
11320                                 }
11321                         }
11322                 } while (others && (notify_plci != NULL));
11323                 if (others)
11324                         plci->li_notify_update = false;
11325         }
11326 }
11327
11328
11329 static void mixer_clear_config(PLCI *plci)
11330 {
11331         DIVA_CAPI_ADAPTER *a;
11332         word i, j;
11333
11334         dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11335                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11336                         (char *)(FILE_), __LINE__));
11337
11338         plci->li_notify_update = false;
11339         plci->li_plci_b_write_pos = 0;
11340         plci->li_plci_b_read_pos = 0;
11341         plci->li_plci_b_req_pos = 0;
11342         a = plci->adapter;
11343         if ((plci->li_bchannel_id != 0)
11344             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11345         {
11346                 i = a->li_base + (plci->li_bchannel_id - 1);
11347                 li_config_table[i].curchnl = 0;
11348                 li_config_table[i].channel = 0;
11349                 li_config_table[i].chflags = 0;
11350                 for (j = 0; j < li_total_channels; j++)
11351                 {
11352                         li_config_table[j].flag_table[i] = 0;
11353                         li_config_table[i].flag_table[j] = 0;
11354                         li_config_table[i].coef_table[j] = 0;
11355                         li_config_table[j].coef_table[i] = 0;
11356                 }
11357                 if (!a->li_pri)
11358                 {
11359                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11360                         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11361                         {
11362                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11363                                 li_config_table[i].curchnl = 0;
11364                                 li_config_table[i].channel = 0;
11365                                 li_config_table[i].chflags = 0;
11366                                 for (j = 0; j < li_total_channels; j++)
11367                                 {
11368                                         li_config_table[i].flag_table[j] = 0;
11369                                         li_config_table[j].flag_table[i] = 0;
11370                                         li_config_table[i].coef_table[j] = 0;
11371                                         li_config_table[j].coef_table[i] = 0;
11372                                 }
11373                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11374                                 {
11375                                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11376                                         li_config_table[i].curchnl = 0;
11377                                         li_config_table[i].channel = 0;
11378                                         li_config_table[i].chflags = 0;
11379                                         for (j = 0; j < li_total_channels; j++)
11380                                         {
11381                                                 li_config_table[i].flag_table[j] = 0;
11382                                                 li_config_table[j].flag_table[i] = 0;
11383                                                 li_config_table[i].coef_table[j] = 0;
11384                                                 li_config_table[j].coef_table[i] = 0;
11385                                         }
11386                                 }
11387                         }
11388                 }
11389         }
11390 }
11391
11392
11393 static void mixer_prepare_switch(dword Id, PLCI *plci)
11394 {
11395
11396         dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11397                         UnMapId(Id), (char *)(FILE_), __LINE__));
11398
11399         do
11400         {
11401                 mixer_indication_coefs_set(Id, plci);
11402         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11403 }
11404
11405
11406 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11407 {
11408         DIVA_CAPI_ADAPTER *a;
11409         word i, j;
11410
11411         dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11412                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11413
11414         a = plci->adapter;
11415         if ((plci->li_bchannel_id != 0)
11416             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11417         {
11418                 i = a->li_base + (plci->li_bchannel_id - 1);
11419                 for (j = 0; j < li_total_channels; j++)
11420                 {
11421                         li_config_table[i].coef_table[j] &= 0xf;
11422                         li_config_table[j].coef_table[i] &= 0xf;
11423                 }
11424                 if (!a->li_pri)
11425                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11426         }
11427         return (GOOD);
11428 }
11429
11430
11431 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11432 {
11433         DIVA_CAPI_ADAPTER *a;
11434         word Info;
11435
11436         dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11437                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11438
11439         Info = GOOD;
11440         a = plci->adapter;
11441         if ((plci->B1_facilities & B1_FACILITY_MIXER)
11442             && (plci->li_bchannel_id != 0)
11443             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11444         {
11445                 switch (plci->adjust_b_state)
11446                 {
11447                 case ADJUST_B_RESTORE_MIXER_1:
11448                         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11449                         {
11450                                 plci->internal_command = plci->adjust_b_command;
11451                                 if (plci_nl_busy(plci))
11452                                 {
11453                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11454                                         break;
11455                                 }
11456                                 xconnect_query_addresses(plci);
11457                                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11458                                 break;
11459                         }
11460                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11461                         Rc = OK;
11462                 case ADJUST_B_RESTORE_MIXER_2:
11463                 case ADJUST_B_RESTORE_MIXER_3:
11464                 case ADJUST_B_RESTORE_MIXER_4:
11465                         if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11466                         {
11467                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11468                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11469                                 Info = _WRONG_STATE;
11470                                 break;
11471                         }
11472                         if (Rc == OK)
11473                         {
11474                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11475                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11476                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11477                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11478                         }
11479                         else if (Rc == 0)
11480                         {
11481                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11482                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11483                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11484                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11485                         }
11486                         if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11487                         {
11488                                 plci->internal_command = plci->adjust_b_command;
11489                                 break;
11490                         }
11491                 case ADJUST_B_RESTORE_MIXER_5:
11492                         xconnect_write_coefs(plci, plci->adjust_b_command);
11493                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11494                         Rc = OK;
11495                 case ADJUST_B_RESTORE_MIXER_6:
11496                         if (!xconnect_write_coefs_process(Id, plci, Rc))
11497                         {
11498                                 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11499                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11500                                 Info = _FACILITY_NOT_SUPPORTED;
11501                                 break;
11502                         }
11503                         if (plci->internal_command)
11504                                 break;
11505                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11506                 case ADJUST_B_RESTORE_MIXER_7:
11507                         break;
11508                 }
11509         }
11510         return (Info);
11511 }
11512
11513
11514 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11515 {
11516         DIVA_CAPI_ADAPTER *a;
11517         word i, internal_command;
11518
11519         dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11520                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11521                         plci->li_cmd));
11522
11523         a = plci->adapter;
11524         internal_command = plci->internal_command;
11525         plci->internal_command = 0;
11526         switch (plci->li_cmd)
11527         {
11528         case LI_REQ_CONNECT:
11529         case LI_REQ_DISCONNECT:
11530         case LI_REQ_SILENT_UPDATE:
11531                 switch (internal_command)
11532                 {
11533                 default:
11534                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11535                         {
11536                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11537                                                                           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11538                         }
11539                 case MIXER_COMMAND_1:
11540                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11541                         {
11542                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11543                                 {
11544                                         dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11545                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11546                                         break;
11547                                 }
11548                                 if (plci->internal_command)
11549                                         return;
11550                         }
11551                         plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11552                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11553                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11554                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11555                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556                         {
11557                                 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11558                         }
11559                         else
11560                         {
11561                                 do
11562                                 {
11563                                         mixer_indication_coefs_set(Id, plci);
11564                                 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11565                         }
11566                 case MIXER_COMMAND_2:
11567                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11568                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11569                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11570                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11571                         {
11572                                 if (!xconnect_write_coefs_process(Id, plci, Rc))
11573                                 {
11574                                         dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11575                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11576                                         if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11577                                         {
11578                                                 do
11579                                                 {
11580                                                         plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11581                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11582                                                         i = (plci->li_plci_b_write_pos == 0) ?
11583                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11584                                                 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11585                                                          && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11586                                         }
11587                                         break;
11588                                 }
11589                                 if (plci->internal_command)
11590                                         return;
11591                         }
11592                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11593                         {
11594                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11595                                                                           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11596                         }
11597                 case MIXER_COMMAND_3:
11598                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11599                         {
11600                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11601                                 {
11602                                         dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11603                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11604                                         break;
11605                                 }
11606                                 if (plci->internal_command)
11607                                         return;
11608                         }
11609                         break;
11610                 }
11611                 break;
11612         }
11613         if ((plci->li_bchannel_id == 0)
11614             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11615         {
11616                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11617                                 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11618         }
11619         else
11620         {
11621                 i = a->li_base + (plci->li_bchannel_id - 1);
11622                 li_config_table[i].curchnl = plci->li_channel_bits;
11623                 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11624                 {
11625                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11626                         li_config_table[i].curchnl = plci->li_channel_bits;
11627                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11628                         {
11629                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11630                                 li_config_table[i].curchnl = plci->li_channel_bits;
11631                         }
11632                 }
11633         }
11634 }
11635
11636
11637 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11638                               dword plci_b_id, byte connect, dword li_flags)
11639 {
11640         word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11641         PLCI *plci_b;
11642         DIVA_CAPI_ADAPTER *a_b;
11643
11644         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11645         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11646         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11647         if (!a->li_pri && (plci->tel == ADV_VOICE)
11648             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11649         {
11650                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11651                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11652                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11653         }
11654         else
11655         {
11656                 ch_a_v = ch_a;
11657                 ch_a_s = ch_a;
11658         }
11659         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11660         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11661             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11662         {
11663                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11664                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11665                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11666         }
11667         else
11668         {
11669                 ch_b_v = ch_b;
11670                 ch_b_s = ch_b;
11671         }
11672         if (connect)
11673         {
11674                 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11675                 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11676                 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11677                 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11678         }
11679         li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11680         li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11681         li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11682         li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11683         if (ch_a_v == ch_b_v)
11684         {
11685                 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11686                 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11687         }
11688         else
11689         {
11690                 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11691                 {
11692                         for (i = 0; i < li_total_channels; i++)
11693                         {
11694                                 if (i != ch_a_v)
11695                                         li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11696                         }
11697                 }
11698                 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11699                 {
11700                         for (i = 0; i < li_total_channels; i++)
11701                         {
11702                                 if (i != ch_a_s)
11703                                         li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11704                         }
11705                 }
11706                 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11707                 {
11708                         for (i = 0; i < li_total_channels; i++)
11709                         {
11710                                 if (i != ch_a_v)
11711                                         li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11712                         }
11713                 }
11714                 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11715                 {
11716                         for (i = 0; i < li_total_channels; i++)
11717                         {
11718                                 if (i != ch_a_s)
11719                                         li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11720                         }
11721                 }
11722         }
11723         if (li_flags & LI_FLAG_CONFERENCE_A_B)
11724         {
11725                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11726                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11727                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11728                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11729         }
11730         if (li_flags & LI_FLAG_CONFERENCE_B_A)
11731         {
11732                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11733                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11734                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11735                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11736         }
11737         if (li_flags & LI_FLAG_MONITOR_A)
11738         {
11739                 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11740                 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11741         }
11742         if (li_flags & LI_FLAG_MONITOR_B)
11743         {
11744                 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11745                 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11746         }
11747         if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11748         {
11749                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751         }
11752         if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11753         {
11754                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11755                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11756         }
11757         if (li_flags & LI_FLAG_MIX_A)
11758         {
11759                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11760                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11761         }
11762         if (li_flags & LI_FLAG_MIX_B)
11763         {
11764                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11765                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11766         }
11767         if (ch_a_v != ch_a_s)
11768         {
11769                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11770                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11771         }
11772         if (ch_b_v != ch_b_s)
11773         {
11774                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11775                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11776         }
11777 }
11778
11779
11780 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11781                                dword plci_b_id, byte connect, dword li_flags)
11782 {
11783         word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11784         PLCI *plci_b;
11785         DIVA_CAPI_ADAPTER *a_b;
11786
11787         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11788         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11789         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11790         if (!a->li_pri && (plci->tel == ADV_VOICE)
11791             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11792         {
11793                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11794                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11795                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11796         }
11797         else
11798         {
11799                 ch_a_v = ch_a;
11800                 ch_a_s = ch_a;
11801         }
11802         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11803         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11804             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11805         {
11806                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11807                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11808                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11809         }
11810         else
11811         {
11812                 ch_b_v = ch_b;
11813                 ch_b_s = ch_b;
11814         }
11815         if (connect)
11816         {
11817                 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11818                 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11819                 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11820                 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11821                 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11822                 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11823         }
11824         li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825         li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826         li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11827         li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11828         li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11829         li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11830         li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11831         li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11832         if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11833         {
11834                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11835                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11836                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11837                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11838         }
11839         if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11840         {
11841                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11842                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11843                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11844                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11845         }
11846         if (li_flags & LI2_FLAG_MONITOR_B)
11847         {
11848                 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11849                 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11850         }
11851         if (li_flags & LI2_FLAG_MIX_B)
11852         {
11853                 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11854                 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11855         }
11856         if (li_flags & LI2_FLAG_MONITOR_X)
11857                 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11858         if (li_flags & LI2_FLAG_MIX_X)
11859                 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11860         if (li_flags & LI2_FLAG_LOOP_B)
11861         {
11862                 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11863                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11864                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11865                 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11866         }
11867         if (li_flags & LI2_FLAG_LOOP_PC)
11868                 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11869         if (li_flags & LI2_FLAG_LOOP_X)
11870                 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11871         if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11872                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11873         if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11874                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11875         if (ch_a_v != ch_a_s)
11876         {
11877                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11878                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11879         }
11880         if (ch_b_v != ch_b_s)
11881         {
11882                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11883                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11884         }
11885 }
11886
11887
11888 static word li_check_main_plci(dword Id, PLCI *plci)
11889 {
11890         if (plci == NULL)
11891         {
11892                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11893                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11894                 return (_WRONG_IDENTIFIER);
11895         }
11896         if (!plci->State
11897             || !plci->NL.Id || plci->nl_remove_id
11898             || (plci->li_bchannel_id == 0))
11899         {
11900                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11901                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11902                 return (_WRONG_STATE);
11903         }
11904         li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11905         return (GOOD);
11906 }
11907
11908
11909 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11910                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11911 {
11912         byte ctlr_b;
11913         PLCI *plci_b;
11914
11915         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11916              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11917         {
11918                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11919                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11920                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11921                 return (NULL);
11922         }
11923         ctlr_b = 0;
11924         if ((plci_b_id & 0x7f) != 0)
11925         {
11926                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11927                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11928                         ctlr_b = 0;
11929         }
11930         if ((ctlr_b == 0)
11931             || (((plci_b_id >> 8) & 0xff) == 0)
11932             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11933         {
11934                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11935                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11936                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11937                 return (NULL);
11938         }
11939         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11940         if (!plci_b->State
11941             || !plci_b->NL.Id || plci_b->nl_remove_id
11942             || (plci_b->li_bchannel_id == 0))
11943         {
11944                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11945                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11946                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11947                 return (NULL);
11948         }
11949         li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11950         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11951             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11952             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11953                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11954         {
11955                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11956                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11957                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11958                 return (NULL);
11959         }
11960         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11961                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11962         {
11963                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11964                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11965                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11966                 return (NULL);
11967         }
11968         return (plci_b);
11969 }
11970
11971
11972 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11973                               dword plci_b_id, word plci_b_write_pos, byte *p_result)
11974 {
11975         byte ctlr_b;
11976         PLCI *plci_b;
11977
11978         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11979              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11980         {
11981                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11982                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11983                 PUT_WORD(p_result, _WRONG_STATE);
11984                 return (NULL);
11985         }
11986         ctlr_b = 0;
11987         if ((plci_b_id & 0x7f) != 0)
11988         {
11989                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11990                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11991                         ctlr_b = 0;
11992         }
11993         if ((ctlr_b == 0)
11994             || (((plci_b_id >> 8) & 0xff) == 0)
11995             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11996         {
11997                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11998                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11999                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12000                 return (NULL);
12001         }
12002         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12003         if (!plci_b->State
12004             || !plci_b->NL.Id || plci_b->nl_remove_id
12005             || (plci_b->li_bchannel_id == 0)
12006             || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12007         {
12008                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12009                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12010                 PUT_WORD(p_result, _WRONG_STATE);
12011                 return (NULL);
12012         }
12013         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12014             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12015             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12016                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12017         {
12018                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12019                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12020                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12021                 return (NULL);
12022         }
12023         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12024                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12025         {
12026                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12027                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12028                 PUT_WORD(p_result, _WRONG_STATE);
12029                 return (NULL);
12030         }
12031         return (plci_b);
12032 }
12033
12034
12035 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12036 {
12037         word Info;
12038         word i;
12039         dword d, li_flags, plci_b_id;
12040         PLCI *plci_b;
12041         API_PARSE li_parms[3];
12042         API_PARSE li_req_parms[3];
12043         API_PARSE li_participant_struct[2];
12044         API_PARSE li_participant_parms[3];
12045         word participant_parms_pos;
12046         byte result_buffer[32];
12047         byte *result;
12048         word result_pos;
12049         word plci_b_write_pos;
12050
12051         dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12052                         UnMapId(Id), (char *)(FILE_), __LINE__));
12053
12054         Info = GOOD;
12055         result = result_buffer;
12056         result_buffer[0] = 0;
12057         if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12058         {
12059                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12060                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12061                 Info = _FACILITY_NOT_SUPPORTED;
12062         }
12063         else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12064         {
12065                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12066                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12067                 Info = _WRONG_MESSAGE_FORMAT;
12068         }
12069         else
12070         {
12071                 result_buffer[0] = 3;
12072                 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12073                 result_buffer[3] = 0;
12074                 switch (GET_WORD(li_parms[0].info))
12075                 {
12076                 case LI_GET_SUPPORTED_SERVICES:
12077                         if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12078                         {
12079                                 result_buffer[0] = 17;
12080                                 result_buffer[3] = 14;
12081                                 PUT_WORD(&result_buffer[4], GOOD);
12082                                 d = 0;
12083                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12084                                         d |= LI_CONFERENCING_SUPPORTED;
12085                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12086                                         d |= LI_MONITORING_SUPPORTED;
12087                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12088                                         d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12089                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12090                                         d |= LI_CROSS_CONTROLLER_SUPPORTED;
12091                                 PUT_DWORD(&result_buffer[6], d);
12092                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12093                                 {
12094                                         d = 0;
12095                                         for (i = 0; i < li_total_channels; i++)
12096                                         {
12097                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12098                                                     && (li_config_table[i].adapter->li_pri
12099                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12100                                                 {
12101                                                         d++;
12102                                                 }
12103                                         }
12104                                 }
12105                                 else
12106                                 {
12107                                         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12108                                 }
12109                                 PUT_DWORD(&result_buffer[10], d / 2);
12110                                 PUT_DWORD(&result_buffer[14], d);
12111                         }
12112                         else
12113                         {
12114                                 result_buffer[0] = 25;
12115                                 result_buffer[3] = 22;
12116                                 PUT_WORD(&result_buffer[4], GOOD);
12117                                 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12118                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12119                                         d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12120                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12121                                         d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12122                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12123                                         d |= LI2_PC_LOOPING_SUPPORTED;
12124                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12125                                         d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12126                                 PUT_DWORD(&result_buffer[6], d);
12127                                 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12128                                 PUT_DWORD(&result_buffer[10], d / 2);
12129                                 PUT_DWORD(&result_buffer[14], d - 1);
12130                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12131                                 {
12132                                         d = 0;
12133                                         for (i = 0; i < li_total_channels; i++)
12134                                         {
12135                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12136                                                     && (li_config_table[i].adapter->li_pri
12137                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12138                                                 {
12139                                                         d++;
12140                                                 }
12141                                         }
12142                                 }
12143                                 PUT_DWORD(&result_buffer[18], d / 2);
12144                                 PUT_DWORD(&result_buffer[22], d - 1);
12145                         }
12146                         break;
12147
12148                 case LI_REQ_CONNECT:
12149                         if (li_parms[1].length == 8)
12150                         {
12151                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12152                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12153                                 {
12154                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12155                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12156                                         Info = _WRONG_MESSAGE_FORMAT;
12157                                         break;
12158                                 }
12159                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12160                                 li_flags = GET_DWORD(li_req_parms[1].info);
12161                                 Info = li_check_main_plci(Id, plci);
12162                                 result_buffer[0] = 9;
12163                                 result_buffer[3] = 6;
12164                                 PUT_DWORD(&result_buffer[4], plci_b_id);
12165                                 PUT_WORD(&result_buffer[8], GOOD);
12166                                 if (Info != GOOD)
12167                                         break;
12168                                 result = plci->saved_msg.info;
12169                                 for (i = 0; i <= result_buffer[0]; i++)
12170                                         result[i] = result_buffer[i];
12171                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12172                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12173                                 if (plci_b == NULL)
12174                                         break;
12175                                 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12176                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12177                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12178                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12179                         }
12180                         else
12181                         {
12182                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12183                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12184                                 {
12185                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12186                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12187                                         Info = _WRONG_MESSAGE_FORMAT;
12188                                         break;
12189                                 }
12190                                 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12191                                 Info = li_check_main_plci(Id, plci);
12192                                 result_buffer[0] = 7;
12193                                 result_buffer[3] = 4;
12194                                 PUT_WORD(&result_buffer[4], Info);
12195                                 result_buffer[6] = 0;
12196                                 if (Info != GOOD)
12197                                         break;
12198                                 result = plci->saved_msg.info;
12199                                 for (i = 0; i <= result_buffer[0]; i++)
12200                                         result[i] = result_buffer[i];
12201                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12202                                 participant_parms_pos = 0;
12203                                 result_pos = 7;
12204                                 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12205                                 while (participant_parms_pos < li_req_parms[1].length)
12206                                 {
12207                                         result[result_pos] = 6;
12208                                         result_pos += 7;
12209                                         PUT_DWORD(&result[result_pos - 6], 0);
12210                                         PUT_WORD(&result[result_pos - 2], GOOD);
12211                                         if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12212                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12213                                         {
12214                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12215                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12216                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12217                                                 break;
12218                                         }
12219                                         if (api_parse(&li_participant_struct[0].info[1],
12220                                                       li_participant_struct[0].length, "dd", li_participant_parms))
12221                                         {
12222                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12223                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12224                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12225                                                 break;
12226                                         }
12227                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12228                                         li_flags = GET_DWORD(li_participant_parms[1].info);
12229                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12230                                         if (sizeof(result) - result_pos < 7)
12231                                         {
12232                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12233                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12234                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12235                                                 break;
12236                                         }
12237                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12238                                         if (plci_b != NULL)
12239                                         {
12240                                                 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12241                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12242                                                         ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12243                                                                       LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12244                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12245                                         }
12246                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12247                                                                        (&li_req_parms[1].info[1]));
12248                                 }
12249                                 result[0] = (byte)(result_pos - 1);
12250                                 result[3] = (byte)(result_pos - 4);
12251                                 result[6] = (byte)(result_pos - 7);
12252                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12253                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12254                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12255                                 {
12256                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12257                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12258                                 }
12259                                 else
12260                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12261                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12262                         }
12263                         mixer_calculate_coefs(a);
12264                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12265                         mixer_notify_update(plci, true);
12266                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12267                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12268                         plci->command = 0;
12269                         plci->li_cmd = GET_WORD(li_parms[0].info);
12270                         start_internal_command(Id, plci, mixer_command);
12271                         return (false);
12272
12273                 case LI_REQ_DISCONNECT:
12274                         if (li_parms[1].length == 4)
12275                         {
12276                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12277                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12278                                 {
12279                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12280                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12281                                         Info = _WRONG_MESSAGE_FORMAT;
12282                                         break;
12283                                 }
12284                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12285                                 Info = li_check_main_plci(Id, plci);
12286                                 result_buffer[0] = 9;
12287                                 result_buffer[3] = 6;
12288                                 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12289                                 PUT_WORD(&result_buffer[8], GOOD);
12290                                 if (Info != GOOD)
12291                                         break;
12292                                 result = plci->saved_msg.info;
12293                                 for (i = 0; i <= result_buffer[0]; i++)
12294                                         result[i] = result_buffer[i];
12295                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12296                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12297                                 if (plci_b == NULL)
12298                                         break;
12299                                 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12300                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12301                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12302                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12303                         }
12304                         else
12305                         {
12306                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12307                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12308                                 {
12309                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12310                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12311                                         Info = _WRONG_MESSAGE_FORMAT;
12312                                         break;
12313                                 }
12314                                 Info = li_check_main_plci(Id, plci);
12315                                 result_buffer[0] = 7;
12316                                 result_buffer[3] = 4;
12317                                 PUT_WORD(&result_buffer[4], Info);
12318                                 result_buffer[6] = 0;
12319                                 if (Info != GOOD)
12320                                         break;
12321                                 result = plci->saved_msg.info;
12322                                 for (i = 0; i <= result_buffer[0]; i++)
12323                                         result[i] = result_buffer[i];
12324                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12325                                 participant_parms_pos = 0;
12326                                 result_pos = 7;
12327                                 while (participant_parms_pos < li_req_parms[0].length)
12328                                 {
12329                                         result[result_pos] = 6;
12330                                         result_pos += 7;
12331                                         PUT_DWORD(&result[result_pos - 6], 0);
12332                                         PUT_WORD(&result[result_pos - 2], GOOD);
12333                                         if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12334                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12335                                         {
12336                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12337                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12338                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12339                                                 break;
12340                                         }
12341                                         if (api_parse(&li_participant_struct[0].info[1],
12342                                                       li_participant_struct[0].length, "d", li_participant_parms))
12343                                         {
12344                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12345                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12346                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12347                                                 break;
12348                                         }
12349                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12350                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12351                                         if (sizeof(result) - result_pos < 7)
12352                                         {
12353                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12354                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12355                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12356                                                 break;
12357                                         }
12358                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12359                                         if (plci_b != NULL)
12360                                         {
12361                                                 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12362                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12363                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12364                                         }
12365                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12366                                                                        (&li_req_parms[0].info[1]));
12367                                 }
12368                                 result[0] = (byte)(result_pos - 1);
12369                                 result[3] = (byte)(result_pos - 4);
12370                                 result[6] = (byte)(result_pos - 7);
12371                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12372                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12373                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12374                                 {
12375                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12376                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12377                                 }
12378                                 else
12379                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12380                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12381                         }
12382                         mixer_calculate_coefs(a);
12383                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12384                         mixer_notify_update(plci, true);
12385                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12386                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12387                         plci->command = 0;
12388                         plci->li_cmd = GET_WORD(li_parms[0].info);
12389                         start_internal_command(Id, plci, mixer_command);
12390                         return (false);
12391
12392                 case LI_REQ_SILENT_UPDATE:
12393                         if (!plci || !plci->State
12394                             || !plci->NL.Id || plci->nl_remove_id
12395                             || (plci->li_bchannel_id == 0)
12396                             || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12397                         {
12398                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12399                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12400                                 return (false);
12401                         }
12402                         plci_b_write_pos = plci->li_plci_b_write_pos;
12403                         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12404                              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12405                         {
12406                                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12407                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12408                                 return (false);
12409                         }
12410                         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12411                         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12412                             || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12413                         {
12414                                 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12415                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12416                         }
12417                         else
12418                                 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12419                         plci->li_plci_b_write_pos = plci_b_write_pos;
12420                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12421                         plci->command = 0;
12422                         plci->li_cmd = GET_WORD(li_parms[0].info);
12423                         start_internal_command(Id, plci, mixer_command);
12424                         return (false);
12425
12426                 default:
12427                         dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12428                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12429                         Info = _FACILITY_NOT_SUPPORTED;
12430                 }
12431         }
12432         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12433               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12434         return (false);
12435 }
12436
12437
12438 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12439 {
12440         dword d;
12441         byte result[12];
12442
12443         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12444                         UnMapId(Id), (char *)(FILE_), __LINE__));
12445
12446         if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12447         {
12448                 do
12449                 {
12450                         d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12451                         if (!(d & LI_PLCI_B_SKIP_FLAG))
12452                         {
12453                                 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12454                                 {
12455                                         if (d & LI_PLCI_B_DISC_FLAG)
12456                                         {
12457                                                 result[0] = 5;
12458                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12459                                                 result[3] = 2;
12460                                                 PUT_WORD(&result[4], _LI_USER_INITIATED);
12461                                         }
12462                                         else
12463                                         {
12464                                                 result[0] = 7;
12465                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12466                                                 result[3] = 4;
12467                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12468                                         }
12469                                 }
12470                                 else
12471                                 {
12472                                         if (d & LI_PLCI_B_DISC_FLAG)
12473                                         {
12474                                                 result[0] = 9;
12475                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12476                                                 result[3] = 6;
12477                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12478                                                 PUT_WORD(&result[8], _LI_USER_INITIATED);
12479                                         }
12480                                         else
12481                                         {
12482                                                 result[0] = 7;
12483                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12484                                                 result[3] = 4;
12485                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12486                                         }
12487                                 }
12488                                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12489                                       "ws", SELECTOR_LINE_INTERCONNECT, result);
12490                         }
12491                         plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12492                                 0 : plci->li_plci_b_read_pos + 1;
12493                 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12494         }
12495 }
12496
12497
12498 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12499 {
12500         word i, j, ch;
12501         struct xconnect_transfer_address_s s,   *p;
12502         DIVA_CAPI_ADAPTER *a;
12503
12504         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12505                         UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12506
12507         a = plci->adapter;
12508         i = 1;
12509         for (i = 1; i < length; i += 16)
12510         {
12511                 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12512                 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12513                 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12514                 ch = msg[i + 12] | (msg[i + 13] << 8);
12515                 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12516                 if (!a->li_pri && (plci->li_bchannel_id == 2))
12517                         j = 1 - j;
12518                 j += a->li_base;
12519                 if (ch & XCONNECT_CHANNEL_PORT_PC)
12520                         p = &(li_config_table[j].send_pc);
12521                 else
12522                         p = &(li_config_table[j].send_b);
12523                 p->card_address.low = s.card_address.low;
12524                 p->card_address.high = s.card_address.high;
12525                 p->offset = s.offset;
12526                 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12527         }
12528         if (plci->internal_command_queue[0]
12529             && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12530                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12531                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12532         {
12533                 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12534                 if (!plci->internal_command)
12535                         next_internal_command(Id, plci);
12536         }
12537         mixer_notify_update(plci, true);
12538 }
12539
12540
12541 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12542 {
12543
12544         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12545                         UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12546
12547 }
12548
12549
12550 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12551 {
12552         word plci_b_write_pos;
12553
12554         plci_b_write_pos = plci->li_plci_b_write_pos;
12555         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12556              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12557         {
12558                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12559                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12560                                 (char *)(FILE_), __LINE__));
12561                 return (false);
12562         }
12563         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12564         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12565         plci->li_plci_b_write_pos = plci_b_write_pos;
12566         return (true);
12567 }
12568
12569
12570 static void mixer_remove(PLCI *plci)
12571 {
12572         DIVA_CAPI_ADAPTER *a;
12573         PLCI *notify_plci;
12574         dword plci_b_id;
12575         word i, j;
12576
12577         dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12578                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12579                         (char *)(FILE_), __LINE__));
12580
12581         a = plci->adapter;
12582         plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12583         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12584         {
12585                 if ((plci->li_bchannel_id != 0)
12586                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12587                 {
12588                         i = a->li_base + (plci->li_bchannel_id - 1);
12589                         if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12590                         {
12591                                 for (j = 0; j < li_total_channels; j++)
12592                                 {
12593                                         if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12594                                             || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12595                                         {
12596                                                 notify_plci = li_config_table[j].plci;
12597                                                 if ((notify_plci != NULL)
12598                                                     && (notify_plci != plci)
12599                                                     && (notify_plci->appl != NULL)
12600                                                     && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12601                                                     && (notify_plci->State)
12602                                                     && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12603                                                 {
12604                                                         mixer_notify_source_removed(notify_plci, plci_b_id);
12605                                                 }
12606                                         }
12607                                 }
12608                                 mixer_clear_config(plci);
12609                                 mixer_calculate_coefs(a);
12610                                 mixer_notify_update(plci, true);
12611                         }
12612                         li_config_table[i].plci = NULL;
12613                         plci->li_bchannel_id = 0;
12614                 }
12615         }
12616 }
12617
12618
12619 /*------------------------------------------------------------------*/
12620 /* Echo canceller facilities                                        */
12621 /*------------------------------------------------------------------*/
12622
12623
12624 static void ec_write_parameters(PLCI *plci)
12625 {
12626         word w;
12627         byte parameter_buffer[6];
12628
12629         dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12630                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12631                         (char *)(FILE_), __LINE__));
12632
12633         parameter_buffer[0] = 5;
12634         parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12635         PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12636         plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12637         w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12638         PUT_WORD(&parameter_buffer[4], w);
12639         add_p(plci, FTY, parameter_buffer);
12640         sig_req(plci, TEL_CTRL, 0);
12641         send_req(plci);
12642 }
12643
12644
12645 static void ec_clear_config(PLCI *plci)
12646 {
12647
12648         dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12649                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12650                         (char *)(FILE_), __LINE__));
12651
12652         plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12653                 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12654         plci->ec_tail_length = 0;
12655 }
12656
12657
12658 static void ec_prepare_switch(dword Id, PLCI *plci)
12659 {
12660
12661         dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12662                         UnMapId(Id), (char *)(FILE_), __LINE__));
12663
12664 }
12665
12666
12667 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12668 {
12669
12670         dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12671                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672
12673         return (GOOD);
12674 }
12675
12676
12677 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12678 {
12679         word Info;
12680
12681         dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12682                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12683
12684         Info = GOOD;
12685         if (plci->B1_facilities & B1_FACILITY_EC)
12686         {
12687                 switch (plci->adjust_b_state)
12688                 {
12689                 case ADJUST_B_RESTORE_EC_1:
12690                         plci->internal_command = plci->adjust_b_command;
12691                         if (plci->sig_req)
12692                         {
12693                                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12694                                 break;
12695                         }
12696                         ec_write_parameters(plci);
12697                         plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12698                         break;
12699                 case ADJUST_B_RESTORE_EC_2:
12700                         if ((Rc != OK) && (Rc != OK_FC))
12701                         {
12702                                 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12703                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12704                                 Info = _WRONG_STATE;
12705                                 break;
12706                         }
12707                         break;
12708                 }
12709         }
12710         return (Info);
12711 }
12712
12713
12714 static void ec_command(dword Id, PLCI *plci, byte Rc)
12715 {
12716         word internal_command, Info;
12717         byte result[8];
12718
12719         dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12720                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12721                         plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12722
12723         Info = GOOD;
12724         if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12725         {
12726                 result[0] = 2;
12727                 PUT_WORD(&result[1], EC_SUCCESS);
12728         }
12729         else
12730         {
12731                 result[0] = 5;
12732                 PUT_WORD(&result[1], plci->ec_cmd);
12733                 result[3] = 2;
12734                 PUT_WORD(&result[4], GOOD);
12735         }
12736         internal_command = plci->internal_command;
12737         plci->internal_command = 0;
12738         switch (plci->ec_cmd)
12739         {
12740         case EC_ENABLE_OPERATION:
12741         case EC_FREEZE_COEFFICIENTS:
12742         case EC_RESUME_COEFFICIENT_UPDATE:
12743         case EC_RESET_COEFFICIENTS:
12744                 switch (internal_command)
12745                 {
12746                 default:
12747                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12748                                                                   B1_FACILITY_EC), EC_COMMAND_1);
12749                 case EC_COMMAND_1:
12750                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12751                         {
12752                                 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12753                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12754                                 Info = _FACILITY_NOT_SUPPORTED;
12755                                 break;
12756                         }
12757                         if (plci->internal_command)
12758                                 return;
12759                 case EC_COMMAND_2:
12760                         if (plci->sig_req)
12761                         {
12762                                 plci->internal_command = EC_COMMAND_2;
12763                                 return;
12764                         }
12765                         plci->internal_command = EC_COMMAND_3;
12766                         ec_write_parameters(plci);
12767                         return;
12768                 case EC_COMMAND_3:
12769                         if ((Rc != OK) && (Rc != OK_FC))
12770                         {
12771                                 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12772                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12773                                 Info = _FACILITY_NOT_SUPPORTED;
12774                                 break;
12775                         }
12776                         break;
12777                 }
12778                 break;
12779
12780         case EC_DISABLE_OPERATION:
12781                 switch (internal_command)
12782                 {
12783                 default:
12784                 case EC_COMMAND_1:
12785                         if (plci->B1_facilities & B1_FACILITY_EC)
12786                         {
12787                                 if (plci->sig_req)
12788                                 {
12789                                         plci->internal_command = EC_COMMAND_1;
12790                                         return;
12791                                 }
12792                                 plci->internal_command = EC_COMMAND_2;
12793                                 ec_write_parameters(plci);
12794                                 return;
12795                         }
12796                         Rc = OK;
12797                 case EC_COMMAND_2:
12798                         if ((Rc != OK) && (Rc != OK_FC))
12799                         {
12800                                 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12801                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12802                                 Info = _FACILITY_NOT_SUPPORTED;
12803                                 break;
12804                         }
12805                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12806                                                                   ~B1_FACILITY_EC), EC_COMMAND_3);
12807                 case EC_COMMAND_3:
12808                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12809                         {
12810                                 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12811                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12812                                 Info = _FACILITY_NOT_SUPPORTED;
12813                                 break;
12814                         }
12815                         if (plci->internal_command)
12816                                 return;
12817                         break;
12818                 }
12819                 break;
12820         }
12821         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12822               "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12823               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12824 }
12825
12826
12827 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12828 {
12829         word Info;
12830         word opt;
12831         API_PARSE ec_parms[3];
12832         byte result[16];
12833
12834         dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12835                         UnMapId(Id), (char *)(FILE_), __LINE__));
12836
12837         Info = GOOD;
12838         result[0] = 0;
12839         if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12840         {
12841                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12842                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12843                 Info = _FACILITY_NOT_SUPPORTED;
12844         }
12845         else
12846         {
12847                 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12848                 {
12849                         if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12850                         {
12851                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12852                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12853                                 Info = _WRONG_MESSAGE_FORMAT;
12854                         }
12855                         else
12856                         {
12857                                 if (plci == NULL)
12858                                 {
12859                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12860                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12861                                         Info = _WRONG_IDENTIFIER;
12862                                 }
12863                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12864                                 {
12865                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12866                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12867                                         Info = _WRONG_STATE;
12868                                 }
12869                                 else
12870                                 {
12871                                         plci->command = 0;
12872                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12873                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12874                                         result[0] = 2;
12875                                         PUT_WORD(&result[1], EC_SUCCESS);
12876                                         if (msg[1].length >= 4)
12877                                         {
12878                                                 opt = GET_WORD(&ec_parms[0].info[2]);
12879                                                 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12880                                                                           LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12881                                                 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12882                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12883                                                 if (opt & EC_DETECT_DISABLE_TONE)
12884                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12885                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12886                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12887                                                 if (msg[1].length >= 6)
12888                                                 {
12889                                                         plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12890                                                 }
12891                                         }
12892                                         switch (plci->ec_cmd)
12893                                         {
12894                                         case EC_ENABLE_OPERATION:
12895                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12896                                                 start_internal_command(Id, plci, ec_command);
12897                                                 return (false);
12898
12899                                         case EC_DISABLE_OPERATION:
12900                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12901                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12902                                                         LEC_RESET_COEFFICIENTS;
12903                                                 start_internal_command(Id, plci, ec_command);
12904                                                 return (false);
12905
12906                                         case EC_FREEZE_COEFFICIENTS:
12907                                                 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12908                                                 start_internal_command(Id, plci, ec_command);
12909                                                 return (false);
12910
12911                                         case EC_RESUME_COEFFICIENT_UPDATE:
12912                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12913                                                 start_internal_command(Id, plci, ec_command);
12914                                                 return (false);
12915
12916                                         case EC_RESET_COEFFICIENTS:
12917                                                 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12918                                                 start_internal_command(Id, plci, ec_command);
12919                                                 return (false);
12920
12921                                         default:
12922                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12923                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12924                                                 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12925                                         }
12926                                 }
12927                         }
12928                 }
12929                 else
12930                 {
12931                         if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12932                         {
12933                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12934                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12935                                 Info = _WRONG_MESSAGE_FORMAT;
12936                         }
12937                         else
12938                         {
12939                                 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12940                                 {
12941                                         result[0] = 11;
12942                                         PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12943                                         result[3] = 8;
12944                                         PUT_WORD(&result[4], GOOD);
12945                                         PUT_WORD(&result[6], 0x0007);
12946                                         PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12947                                         PUT_WORD(&result[10], 0);
12948                                 }
12949                                 else if (plci == NULL)
12950                                 {
12951                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12952                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12953                                         Info = _WRONG_IDENTIFIER;
12954                                 }
12955                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12956                                 {
12957                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12958                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12959                                         Info = _WRONG_STATE;
12960                                 }
12961                                 else
12962                                 {
12963                                         plci->command = 0;
12964                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12965                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12966                                         result[0] = 5;
12967                                         PUT_WORD(&result[1], plci->ec_cmd);
12968                                         result[3] = 2;
12969                                         PUT_WORD(&result[4], GOOD);
12970                                         plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12971                                                                   LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12972                                         plci->ec_tail_length = 0;
12973                                         if (ec_parms[1].length >= 2)
12974                                         {
12975                                                 opt = GET_WORD(&ec_parms[1].info[1]);
12976                                                 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12977                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12978                                                 if (opt & EC_DETECT_DISABLE_TONE)
12979                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12980                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12981                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12982                                                 if (ec_parms[1].length >= 4)
12983                                                 {
12984                                                         plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12985                                                 }
12986                                         }
12987                                         switch (plci->ec_cmd)
12988                                         {
12989                                         case EC_ENABLE_OPERATION:
12990                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12991                                                 start_internal_command(Id, plci, ec_command);
12992                                                 return (false);
12993
12994                                         case EC_DISABLE_OPERATION:
12995                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12996                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12997                                                         LEC_RESET_COEFFICIENTS;
12998                                                 start_internal_command(Id, plci, ec_command);
12999                                                 return (false);
13000
13001                                         default:
13002                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
13003                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13004                                                 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13005                                         }
13006                                 }
13007                         }
13008                 }
13009         }
13010         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13011               "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13012               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13013         return (false);
13014 }
13015
13016
13017 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13018 {
13019         byte result[8];
13020
13021         dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13022                         UnMapId(Id), (char *)(FILE_), __LINE__));
13023
13024         if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13025         {
13026                 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13027                 {
13028                         result[0] = 2;
13029                         PUT_WORD(&result[1], 0);
13030                         switch (msg[1])
13031                         {
13032                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13033                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13034                                 break;
13035                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13036                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13037                                 break;
13038                         case LEC_DISABLE_RELEASED:
13039                                 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13040                                 break;
13041                         }
13042                 }
13043                 else
13044                 {
13045                         result[0] = 5;
13046                         PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13047                         result[3] = 2;
13048                         PUT_WORD(&result[4], 0);
13049                         switch (msg[1])
13050                         {
13051                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13052                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13053                                 break;
13054                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13055                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13056                                 break;
13057                         case LEC_DISABLE_RELEASED:
13058                                 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13059                                 break;
13060                         }
13061                 }
13062                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13063                       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13064         }
13065 }
13066
13067
13068
13069 /*------------------------------------------------------------------*/
13070 /* Advanced voice                                                   */
13071 /*------------------------------------------------------------------*/
13072
13073 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13074 {
13075         DIVA_CAPI_ADAPTER *a;
13076         word i;
13077         byte *p;
13078
13079         word w, n, j, k;
13080         byte ch_map[MIXER_CHANNELS_BRI];
13081
13082         byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13083
13084         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13085                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13086                         (char *)(FILE_), __LINE__, write_command));
13087
13088         a = plci->adapter;
13089         p = coef_buffer + 1;
13090         *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13091         i = 0;
13092         while (i + sizeof(word) <= a->adv_voice_coef_length)
13093         {
13094                 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13095                 p += 2;
13096                 i += 2;
13097         }
13098         while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13099         {
13100                 PUT_WORD(p, 0x8000);
13101                 p += 2;
13102                 i += 2;
13103         }
13104
13105         if (!a->li_pri && (plci->li_bchannel_id == 0))
13106         {
13107                 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13108                 {
13109                         plci->li_bchannel_id = 1;
13110                         li_config_table[a->li_base].plci = plci;
13111                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13112                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13113                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13114                 }
13115                 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13116                 {
13117                         plci->li_bchannel_id = 2;
13118                         li_config_table[a->li_base + 1].plci = plci;
13119                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13120                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13121                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13122                 }
13123         }
13124         if (!a->li_pri && (plci->li_bchannel_id != 0)
13125             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13126         {
13127                 i = a->li_base + (plci->li_bchannel_id - 1);
13128                 switch (write_command)
13129                 {
13130                 case ADV_VOICE_WRITE_ACTIVATION:
13131                         j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13132                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13133                         if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13134                         {
13135                                 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13136                                 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13137                         }
13138                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13139                         {
13140                                 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13141                                 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13142                                 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13143                                 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13144                         }
13145                         mixer_calculate_coefs(a);
13146                         li_config_table[i].curchnl = li_config_table[i].channel;
13147                         li_config_table[j].curchnl = li_config_table[j].channel;
13148                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13149                                 li_config_table[k].curchnl = li_config_table[k].channel;
13150                         break;
13151
13152                 case ADV_VOICE_WRITE_DEACTIVATION:
13153                         for (j = 0; j < li_total_channels; j++)
13154                         {
13155                                 li_config_table[i].flag_table[j] = 0;
13156                                 li_config_table[j].flag_table[i] = 0;
13157                         }
13158                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13159                         for (j = 0; j < li_total_channels; j++)
13160                         {
13161                                 li_config_table[k].flag_table[j] = 0;
13162                                 li_config_table[j].flag_table[k] = 0;
13163                         }
13164                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13165                         {
13166                                 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13167                                 for (j = 0; j < li_total_channels; j++)
13168                                 {
13169                                         li_config_table[k].flag_table[j] = 0;
13170                                         li_config_table[j].flag_table[k] = 0;
13171                                 }
13172                         }
13173                         mixer_calculate_coefs(a);
13174                         break;
13175                 }
13176                 if (plci->B1_facilities & B1_FACILITY_MIXER)
13177                 {
13178                         w = 0;
13179                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13180                                 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13181                         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13182                                 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13183                         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13184                                 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13185                         *(p++) = (byte) w;
13186                         *(p++) = (byte)(w >> 8);
13187                         for (j = 0; j < sizeof(ch_map); j += 2)
13188                         {
13189                                 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13190                                 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13191                         }
13192                         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13193                         {
13194                                 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13195                                 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13196                                 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13197                                 {
13198                                         *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13199                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13200                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13201                                 }
13202                                 else
13203                                 {
13204                                         *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13205                                                 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13206                                 }
13207                         }
13208                 }
13209                 else
13210                 {
13211                         for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212                                 *(p++) = a->adv_voice_coef_buffer[i];
13213                 }
13214         }
13215         else
13216
13217         {
13218                 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13219                         *(p++) = a->adv_voice_coef_buffer[i];
13220         }
13221         coef_buffer[0] = (p - coef_buffer) - 1;
13222         add_p(plci, FTY, coef_buffer);
13223         sig_req(plci, TEL_CTRL, 0);
13224         send_req(plci);
13225 }
13226
13227
13228 static void adv_voice_clear_config(PLCI *plci)
13229 {
13230         DIVA_CAPI_ADAPTER *a;
13231
13232         word i, j;
13233
13234
13235         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13236                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13237                         (char *)(FILE_), __LINE__));
13238
13239         a = plci->adapter;
13240         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13241         {
13242                 a->adv_voice_coef_length = 0;
13243
13244                 if (!a->li_pri && (plci->li_bchannel_id != 0)
13245                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13246                 {
13247                         i = a->li_base + (plci->li_bchannel_id - 1);
13248                         li_config_table[i].curchnl = 0;
13249                         li_config_table[i].channel = 0;
13250                         li_config_table[i].chflags = 0;
13251                         for (j = 0; j < li_total_channels; j++)
13252                         {
13253                                 li_config_table[i].flag_table[j] = 0;
13254                                 li_config_table[j].flag_table[i] = 0;
13255                                 li_config_table[i].coef_table[j] = 0;
13256                                 li_config_table[j].coef_table[i] = 0;
13257                         }
13258                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13259                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13260                         li_config_table[i].curchnl = 0;
13261                         li_config_table[i].channel = 0;
13262                         li_config_table[i].chflags = 0;
13263                         for (j = 0; j < li_total_channels; j++)
13264                         {
13265                                 li_config_table[i].flag_table[j] = 0;
13266                                 li_config_table[j].flag_table[i] = 0;
13267                                 li_config_table[i].coef_table[j] = 0;
13268                                 li_config_table[j].coef_table[i] = 0;
13269                         }
13270                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13271                         {
13272                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13273                                 li_config_table[i].curchnl = 0;
13274                                 li_config_table[i].channel = 0;
13275                                 li_config_table[i].chflags = 0;
13276                                 for (j = 0; j < li_total_channels; j++)
13277                                 {
13278                                         li_config_table[i].flag_table[j] = 0;
13279                                         li_config_table[j].flag_table[i] = 0;
13280                                         li_config_table[i].coef_table[j] = 0;
13281                                         li_config_table[j].coef_table[i] = 0;
13282                                 }
13283                         }
13284                 }
13285
13286         }
13287 }
13288
13289
13290 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13291 {
13292
13293         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13294                         UnMapId(Id), (char *)(FILE_), __LINE__));
13295
13296 }
13297
13298
13299 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13300 {
13301
13302         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13303                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13304
13305         return (GOOD);
13306 }
13307
13308
13309 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13310 {
13311         DIVA_CAPI_ADAPTER *a;
13312         word Info;
13313
13314         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13315                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13316
13317         Info = GOOD;
13318         a = plci->adapter;
13319         if ((plci->B1_facilities & B1_FACILITY_VOICE)
13320             && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13321         {
13322                 switch (plci->adjust_b_state)
13323                 {
13324                 case ADJUST_B_RESTORE_VOICE_1:
13325                         plci->internal_command = plci->adjust_b_command;
13326                         if (plci->sig_req)
13327                         {
13328                                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13329                                 break;
13330                         }
13331                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13332                         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13333                         break;
13334                 case ADJUST_B_RESTORE_VOICE_2:
13335                         if ((Rc != OK) && (Rc != OK_FC))
13336                         {
13337                                 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13338                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13339                                 Info = _WRONG_STATE;
13340                                 break;
13341                         }
13342                         break;
13343                 }
13344         }
13345         return (Info);
13346 }
13347
13348
13349
13350
13351 /*------------------------------------------------------------------*/
13352 /* B1 resource switching                                            */
13353 /*------------------------------------------------------------------*/
13354
13355 static byte b1_facilities_table[] =
13356 {
13357         0x00,  /* 0  No bchannel resources      */
13358         0x00,  /* 1  Codec (automatic law)      */
13359         0x00,  /* 2  Codec (A-law)              */
13360         0x00,  /* 3  Codec (y-law)              */
13361         0x00,  /* 4  HDLC for X.21              */
13362         0x00,  /* 5  HDLC                       */
13363         0x00,  /* 6  External Device 0          */
13364         0x00,  /* 7  External Device 1          */
13365         0x00,  /* 8  HDLC 56k                   */
13366         0x00,  /* 9  Transparent                */
13367         0x00,  /* 10 Loopback to network        */
13368         0x00,  /* 11 Test pattern to net        */
13369         0x00,  /* 12 Rate adaptation sync       */
13370         0x00,  /* 13 Rate adaptation async      */
13371         0x00,  /* 14 R-Interface                */
13372         0x00,  /* 15 HDLC 128k leased line      */
13373         0x00,  /* 16 FAX                        */
13374         0x00,  /* 17 Modem async                */
13375         0x00,  /* 18 Modem sync HDLC            */
13376         0x00,  /* 19 V.110 async HDLC           */
13377         0x12,  /* 20 Adv voice (Trans,mixer)    */
13378         0x00,  /* 21 Codec connected to IC      */
13379         0x0c,  /* 22 Trans,DTMF                 */
13380         0x1e,  /* 23 Trans,DTMF+mixer           */
13381         0x1f,  /* 24 Trans,DTMF+mixer+local     */
13382         0x13,  /* 25 Trans,mixer+local          */
13383         0x12,  /* 26 HDLC,mixer                 */
13384         0x12,  /* 27 HDLC 56k,mixer             */
13385         0x2c,  /* 28 Trans,LEC+DTMF             */
13386         0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13387         0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13388         0x2c,  /* 31 RTP,LEC+DTMF               */
13389         0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13390         0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13391         0x00,  /* 34 Signaling task             */
13392         0x00,  /* 35 PIAFS                      */
13393         0x0c,  /* 36 Trans,DTMF+TONE            */
13394         0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13395         0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13396 };
13397
13398
13399 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13400 {
13401         word b1_facilities;
13402
13403         b1_facilities = b1_facilities_table[b1_resource];
13404         if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13405         {
13406
13407                 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13408                       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13409
13410                 {
13411                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13412                                 b1_facilities |= B1_FACILITY_DTMFX;
13413                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13414                                 b1_facilities |= B1_FACILITY_DTMFR;
13415                 }
13416         }
13417         if ((b1_resource == 17) || (b1_resource == 18))
13418         {
13419                 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13420                         b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13421         }
13422 /*
13423   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13424   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13425   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13426 */
13427         return (b1_facilities);
13428 }
13429
13430
13431 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13432 {
13433         byte b;
13434
13435         switch (b1_resource)
13436         {
13437         case 5:
13438         case 26:
13439                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13440                         b = 26;
13441                 else
13442                         b = 5;
13443                 break;
13444
13445         case 8:
13446         case 27:
13447                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13448                         b = 27;
13449                 else
13450                         b = 8;
13451                 break;
13452
13453         case 9:
13454         case 20:
13455         case 22:
13456         case 23:
13457         case 24:
13458         case 25:
13459         case 28:
13460         case 29:
13461         case 30:
13462         case 36:
13463         case 37:
13464         case 38:
13465                 if (b1_facilities & B1_FACILITY_EC)
13466                 {
13467                         if (b1_facilities & B1_FACILITY_LOCAL)
13468                                 b = 30;
13469                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13470                                 b = 29;
13471                         else
13472                                 b = 28;
13473                 }
13474
13475                 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13476                          && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13477                              || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13478                 {
13479                         if (b1_facilities & B1_FACILITY_LOCAL)
13480                                 b = 38;
13481                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482                                 b = 37;
13483                         else
13484                                 b = 36;
13485                 }
13486
13487                 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13488                           && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13489                          || ((b1_facilities & B1_FACILITY_DTMFR)
13490                              && ((b1_facilities & B1_FACILITY_MIXER)
13491                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13492                          || ((b1_facilities & B1_FACILITY_DTMFX)
13493                              && ((b1_facilities & B1_FACILITY_MIXER)
13494                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13495                 {
13496                         if (b1_facilities & B1_FACILITY_LOCAL)
13497                                 b = 24;
13498                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13499                                 b = 23;
13500                         else
13501                                 b = 22;
13502                 }
13503                 else
13504                 {
13505                         if (b1_facilities & B1_FACILITY_LOCAL)
13506                                 b = 25;
13507                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13508                                 b = 20;
13509                         else
13510                                 b = 9;
13511                 }
13512                 break;
13513
13514         case 31:
13515         case 32:
13516         case 33:
13517                 if (b1_facilities & B1_FACILITY_LOCAL)
13518                         b = 33;
13519                 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520                         b = 32;
13521                 else
13522                         b = 31;
13523                 break;
13524
13525         default:
13526                 b = b1_resource;
13527         }
13528         dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13529                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13530                         (char *)(FILE_), __LINE__,
13531                         b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13532         return (b);
13533 }
13534
13535
13536 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13537 {
13538         word removed_facilities;
13539
13540         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13541                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13542                         (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13543                         new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13544
13545         new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13546         removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13547
13548         if (removed_facilities & B1_FACILITY_EC)
13549                 ec_clear_config(plci);
13550
13551
13552         if (removed_facilities & B1_FACILITY_DTMFR)
13553         {
13554                 dtmf_rec_clear_config(plci);
13555                 dtmf_parameter_clear_config(plci);
13556         }
13557         if (removed_facilities & B1_FACILITY_DTMFX)
13558                 dtmf_send_clear_config(plci);
13559
13560
13561         if (removed_facilities & B1_FACILITY_MIXER)
13562                 mixer_clear_config(plci);
13563
13564         if (removed_facilities & B1_FACILITY_VOICE)
13565                 adv_voice_clear_config(plci);
13566         plci->B1_facilities = new_b1_facilities;
13567 }
13568
13569
13570 static void adjust_b_clear(PLCI *plci)
13571 {
13572
13573         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13574                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13575                         (char *)(FILE_), __LINE__));
13576
13577         plci->adjust_b_restore = false;
13578 }
13579
13580
13581 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13582 {
13583         word Info;
13584         byte b1_resource;
13585         NCCI *ncci_ptr;
13586         API_PARSE bp[2];
13587
13588         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13589                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13590
13591         Info = GOOD;
13592         switch (plci->adjust_b_state)
13593         {
13594         case ADJUST_B_START:
13595                 if ((plci->adjust_b_parms_msg == NULL)
13596                     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13597                     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13598                                                  ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13599                 {
13600                         b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13601                                 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13602                         if (b1_resource == plci->B1_resource)
13603                         {
13604                                 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13605                                 break;
13606                         }
13607                         if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13608                         {
13609                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13610                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13611                                                 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13612                                 Info = _WRONG_STATE;
13613                                 break;
13614                         }
13615                 }
13616                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13617                 {
13618
13619                         mixer_prepare_switch(Id, plci);
13620
13621
13622                         dtmf_prepare_switch(Id, plci);
13623                         dtmf_parameter_prepare_switch(Id, plci);
13624
13625
13626                         ec_prepare_switch(Id, plci);
13627
13628                         adv_voice_prepare_switch(Id, plci);
13629                 }
13630                 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13631                 Rc = OK;
13632         case ADJUST_B_SAVE_MIXER_1:
13633                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634                 {
13635
13636                         Info = mixer_save_config(Id, plci, Rc);
13637                         if ((Info != GOOD) || plci->internal_command)
13638                                 break;
13639
13640                 }
13641                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13642                 Rc = OK;
13643         case ADJUST_B_SAVE_DTMF_1:
13644                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13645                 {
13646
13647                         Info = dtmf_save_config(Id, plci, Rc);
13648                         if ((Info != GOOD) || plci->internal_command)
13649                                 break;
13650
13651                 }
13652                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13653         case ADJUST_B_REMOVE_L23_1:
13654                 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13655                     && plci->NL.Id && !plci->nl_remove_id)
13656                 {
13657                         plci->internal_command = plci->adjust_b_command;
13658                         if (plci->adjust_b_ncci != 0)
13659                         {
13660                                 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13661                                 while (ncci_ptr->data_pending)
13662                                 {
13663                                         plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13664                                         data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13665                                 }
13666                                 while (ncci_ptr->data_ack_pending)
13667                                         data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13668                         }
13669                         nl_req_ncci(plci, REMOVE,
13670                                     (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13671                         send_req(plci);
13672                         plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13673                         break;
13674                 }
13675                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13676                 Rc = OK;
13677         case ADJUST_B_REMOVE_L23_2:
13678                 if ((Rc != OK) && (Rc != OK_FC))
13679                 {
13680                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13681                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13682                         Info = _WRONG_STATE;
13683                         break;
13684                 }
13685                 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13686                 {
13687                         if (plci_nl_busy(plci))
13688                         {
13689                                 plci->internal_command = plci->adjust_b_command;
13690                                 break;
13691                         }
13692                 }
13693                 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13694                 Rc = OK;
13695         case ADJUST_B_SAVE_EC_1:
13696                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13697                 {
13698
13699                         Info = ec_save_config(Id, plci, Rc);
13700                         if ((Info != GOOD) || plci->internal_command)
13701                                 break;
13702
13703                 }
13704                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13705                 Rc = OK;
13706         case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13707                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708                 {
13709
13710                         Info = dtmf_parameter_save_config(Id, plci, Rc);
13711                         if ((Info != GOOD) || plci->internal_command)
13712                                 break;
13713
13714                 }
13715                 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13716                 Rc = OK;
13717         case ADJUST_B_SAVE_VOICE_1:
13718                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13719                 {
13720                         Info = adv_voice_save_config(Id, plci, Rc);
13721                         if ((Info != GOOD) || plci->internal_command)
13722                                 break;
13723                 }
13724                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13725         case ADJUST_B_SWITCH_L1_1:
13726                 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13727                 {
13728                         if (plci->sig_req)
13729                         {
13730                                 plci->internal_command = plci->adjust_b_command;
13731                                 break;
13732                         }
13733                         if (plci->adjust_b_parms_msg != NULL)
13734                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13735                         else
13736                                 api_load_msg(&plci->B_protocol, bp);
13737                         Info = add_b1(plci, bp,
13738                                       (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13739                                       plci->adjust_b_facilities);
13740                         if (Info != GOOD)
13741                         {
13742                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13743                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13744                                                 plci->B1_resource, plci->adjust_b_facilities));
13745                                 break;
13746                         }
13747                         plci->internal_command = plci->adjust_b_command;
13748                         sig_req(plci, RESOURCES, 0);
13749                         send_req(plci);
13750                         plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13751                         break;
13752                 }
13753                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13754                 Rc = OK;
13755         case ADJUST_B_SWITCH_L1_2:
13756                 if ((Rc != OK) && (Rc != OK_FC))
13757                 {
13758                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13759                                         UnMapId(Id), (char *)(FILE_), __LINE__,
13760                                         Rc, plci->B1_resource, plci->adjust_b_facilities));
13761                         Info = _WRONG_STATE;
13762                         break;
13763                 }
13764                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13765                 Rc = OK;
13766         case ADJUST_B_RESTORE_VOICE_1:
13767         case ADJUST_B_RESTORE_VOICE_2:
13768                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13769                 {
13770                         Info = adv_voice_restore_config(Id, plci, Rc);
13771                         if ((Info != GOOD) || plci->internal_command)
13772                                 break;
13773                 }
13774                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13775                 Rc = OK;
13776         case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13777         case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13778                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13779                 {
13780
13781                         Info = dtmf_parameter_restore_config(Id, plci, Rc);
13782                         if ((Info != GOOD) || plci->internal_command)
13783                                 break;
13784
13785                 }
13786                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13787                 Rc = OK;
13788         case ADJUST_B_RESTORE_EC_1:
13789         case ADJUST_B_RESTORE_EC_2:
13790                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13791                 {
13792
13793                         Info = ec_restore_config(Id, plci, Rc);
13794                         if ((Info != GOOD) || plci->internal_command)
13795                                 break;
13796
13797                 }
13798                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13799         case ADJUST_B_ASSIGN_L23_1:
13800                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13801                 {
13802                         if (plci_nl_busy(plci))
13803                         {
13804                                 plci->internal_command = plci->adjust_b_command;
13805                                 break;
13806                         }
13807                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13808                                 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13809                         if (plci->adjust_b_parms_msg != NULL)
13810                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13811                         else
13812                                 api_load_msg(&plci->B_protocol, bp);
13813                         Info = add_b23(plci, bp);
13814                         if (Info != GOOD)
13815                         {
13816                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13817                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13818                                 break;
13819                         }
13820                         plci->internal_command = plci->adjust_b_command;
13821                         nl_req_ncci(plci, ASSIGN, 0);
13822                         send_req(plci);
13823                         plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13824                         break;
13825                 }
13826                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13827                 Rc = ASSIGN_OK;
13828         case ADJUST_B_ASSIGN_L23_2:
13829                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13830                 {
13831                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13832                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13833                         Info = _WRONG_STATE;
13834                         break;
13835                 }
13836                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13837                 {
13838                         if (Rc != ASSIGN_OK)
13839                         {
13840                                 plci->internal_command = plci->adjust_b_command;
13841                                 break;
13842                         }
13843                 }
13844                 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13845                 {
13846                         plci->adjust_b_restore = true;
13847                         break;
13848                 }
13849                 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13850         case ADJUST_B_CONNECT_1:
13851                 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13852                 {
13853                         plci->internal_command = plci->adjust_b_command;
13854                         if (plci_nl_busy(plci))
13855                                 break;
13856                         nl_req_ncci(plci, N_CONNECT, 0);
13857                         send_req(plci);
13858                         plci->adjust_b_state = ADJUST_B_CONNECT_2;
13859                         break;
13860                 }
13861                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13862                 Rc = OK;
13863         case ADJUST_B_CONNECT_2:
13864         case ADJUST_B_CONNECT_3:
13865         case ADJUST_B_CONNECT_4:
13866                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13867                 {
13868                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13869                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13870                         Info = _WRONG_STATE;
13871                         break;
13872                 }
13873                 if (Rc == OK)
13874                 {
13875                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13876                         {
13877                                 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13878                                 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13879                         }
13880                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881                                 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13882                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13883                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13884                 }
13885                 else if (Rc == 0)
13886                 {
13887                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13888                                 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13889                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13890                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13891                 }
13892                 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13893                 {
13894                         plci->internal_command = plci->adjust_b_command;
13895                         break;
13896                 }
13897                 Rc = OK;
13898         case ADJUST_B_RESTORE_DTMF_1:
13899         case ADJUST_B_RESTORE_DTMF_2:
13900                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13901                 {
13902
13903                         Info = dtmf_restore_config(Id, plci, Rc);
13904                         if ((Info != GOOD) || plci->internal_command)
13905                                 break;
13906
13907                 }
13908                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13909                 Rc = OK;
13910         case ADJUST_B_RESTORE_MIXER_1:
13911         case ADJUST_B_RESTORE_MIXER_2:
13912         case ADJUST_B_RESTORE_MIXER_3:
13913         case ADJUST_B_RESTORE_MIXER_4:
13914         case ADJUST_B_RESTORE_MIXER_5:
13915         case ADJUST_B_RESTORE_MIXER_6:
13916         case ADJUST_B_RESTORE_MIXER_7:
13917                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13918                 {
13919
13920                         Info = mixer_restore_config(Id, plci, Rc);
13921                         if ((Info != GOOD) || plci->internal_command)
13922                                 break;
13923
13924                 }
13925                 plci->adjust_b_state = ADJUST_B_END;
13926         case ADJUST_B_END:
13927                 break;
13928         }
13929         return (Info);
13930 }
13931
13932
13933 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13934 {
13935
13936         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13937                         UnMapId(Id), (char *)(FILE_), __LINE__,
13938                         plci->B1_resource, b1_facilities));
13939
13940         plci->adjust_b_parms_msg = bp_msg;
13941         plci->adjust_b_facilities = b1_facilities;
13942         plci->adjust_b_command = internal_command;
13943         plci->adjust_b_ncci = (word)(Id >> 16);
13944         if ((bp_msg == NULL) && (plci->B1_resource == 0))
13945                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13946         else
13947                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13948         plci->adjust_b_state = ADJUST_B_START;
13949         dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13950                         UnMapId(Id), (char *)(FILE_), __LINE__,
13951                         plci->B1_resource, b1_facilities));
13952 }
13953
13954
13955 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13956 {
13957         word internal_command;
13958
13959         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13960                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13961
13962         internal_command = plci->internal_command;
13963         plci->internal_command = 0;
13964         switch (internal_command)
13965         {
13966         default:
13967                 plci->command = 0;
13968                 if (plci->req_in != 0)
13969                 {
13970                         plci->internal_command = ADJUST_B_RESTORE_1;
13971                         break;
13972                 }
13973                 Rc = OK;
13974         case ADJUST_B_RESTORE_1:
13975                 if ((Rc != OK) && (Rc != OK_FC))
13976                 {
13977                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13978                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13979                 }
13980                 plci->adjust_b_parms_msg = NULL;
13981                 plci->adjust_b_facilities = plci->B1_facilities;
13982                 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13983                 plci->adjust_b_ncci = (word)(Id >> 16);
13984                 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13985                 plci->adjust_b_state = ADJUST_B_START;
13986                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13987                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13988         case ADJUST_B_RESTORE_2:
13989                 if (adjust_b_process(Id, plci, Rc) != GOOD)
13990                 {
13991                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13992                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13993                 }
13994                 if (plci->internal_command)
13995                         break;
13996                 break;
13997         }
13998 }
13999
14000
14001 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
14002 {
14003         word Info;
14004         word internal_command;
14005
14006         dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14007                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14008
14009         Info = GOOD;
14010         internal_command = plci->internal_command;
14011         plci->internal_command = 0;
14012         switch (internal_command)
14013         {
14014         default:
14015                 plci->command = 0;
14016                 plci->adjust_b_parms_msg = NULL;
14017                 plci->adjust_b_facilities = plci->B1_facilities;
14018                 plci->adjust_b_command = RESET_B3_COMMAND_1;
14019                 plci->adjust_b_ncci = (word)(Id >> 16);
14020                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14021                 plci->adjust_b_state = ADJUST_B_START;
14022                 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14023                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14024         case RESET_B3_COMMAND_1:
14025                 Info = adjust_b_process(Id, plci, Rc);
14026                 if (Info != GOOD)
14027                 {
14028                         dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14029                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14030                         break;
14031                 }
14032                 if (plci->internal_command)
14033                         return;
14034                 break;
14035         }
14036 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14037         sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14038 }
14039
14040
14041 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14042 {
14043         word Info;
14044         word internal_command;
14045         byte esc_chi[3];
14046
14047         dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14048                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14049
14050         Info = GOOD;
14051         internal_command = plci->internal_command;
14052         plci->internal_command = 0;
14053         switch (internal_command)
14054         {
14055         default:
14056                 plci->command = 0;
14057                 plci->adjust_b_parms_msg = &plci->saved_msg;
14058                 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14059                         plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14060                 else
14061                         plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14062                 plci->adjust_b_command = SELECT_B_COMMAND_1;
14063                 plci->adjust_b_ncci = (word)(Id >> 16);
14064                 if (plci->saved_msg.parms[0].length == 0)
14065                 {
14066                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14067                                 ADJUST_B_MODE_NO_RESOURCE;
14068                 }
14069                 else
14070                 {
14071                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14072                                 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14073                 }
14074                 plci->adjust_b_state = ADJUST_B_START;
14075                 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14076                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14077         case SELECT_B_COMMAND_1:
14078                 Info = adjust_b_process(Id, plci, Rc);
14079                 if (Info != GOOD)
14080                 {
14081                         dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14082                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14083                         break;
14084                 }
14085                 if (plci->internal_command)
14086                         return;
14087                 if (plci->tel == ADV_VOICE)
14088                 {
14089                         esc_chi[0] = 0x02;
14090                         esc_chi[1] = 0x18;
14091                         esc_chi[2] = plci->b_channel;
14092                         SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14093                 }
14094                 break;
14095         }
14096         sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14097 }
14098
14099
14100 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14101 {
14102         word internal_command;
14103
14104         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14105                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14106
14107         internal_command = plci->internal_command;
14108         plci->internal_command = 0;
14109         switch (internal_command)
14110         {
14111         default:
14112                 plci->command = 0;
14113         case FAX_CONNECT_ACK_COMMAND_1:
14114                 if (plci_nl_busy(plci))
14115                 {
14116                         plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14117                         return;
14118                 }
14119                 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14120                 plci->NData[0].P = plci->fax_connect_info_buffer;
14121                 plci->NData[0].PLength = plci->fax_connect_info_length;
14122                 plci->NL.X = plci->NData;
14123                 plci->NL.ReqCh = 0;
14124                 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14125                 plci->adapter->request(&plci->NL);
14126                 return;
14127         case FAX_CONNECT_ACK_COMMAND_2:
14128                 if ((Rc != OK) && (Rc != OK_FC))
14129                 {
14130                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14131                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14132                         break;
14133                 }
14134         }
14135         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14136             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14137         {
14138                 if (plci->B3_prot == 4)
14139                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14140                 else
14141                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14142                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14143         }
14144 }
14145
14146
14147 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14148 {
14149         word internal_command;
14150
14151         dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14152                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14153
14154         internal_command = plci->internal_command;
14155         plci->internal_command = 0;
14156         switch (internal_command)
14157         {
14158         default:
14159                 plci->command = 0;
14160         case FAX_EDATA_ACK_COMMAND_1:
14161                 if (plci_nl_busy(plci))
14162                 {
14163                         plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14164                         return;
14165                 }
14166                 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14167                 plci->NData[0].P = plci->fax_connect_info_buffer;
14168                 plci->NData[0].PLength = plci->fax_edata_ack_length;
14169                 plci->NL.X = plci->NData;
14170                 plci->NL.ReqCh = 0;
14171                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14172                 plci->adapter->request(&plci->NL);
14173                 return;
14174         case FAX_EDATA_ACK_COMMAND_2:
14175                 if ((Rc != OK) && (Rc != OK_FC))
14176                 {
14177                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14178                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14179                         break;
14180                 }
14181         }
14182 }
14183
14184
14185 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14186 {
14187         word Info;
14188         word internal_command;
14189
14190         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14191                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14192
14193         Info = GOOD;
14194         internal_command = plci->internal_command;
14195         plci->internal_command = 0;
14196         switch (internal_command)
14197         {
14198         default:
14199                 plci->command = 0;
14200         case FAX_CONNECT_INFO_COMMAND_1:
14201                 if (plci_nl_busy(plci))
14202                 {
14203                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14204                         return;
14205                 }
14206                 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14207                 plci->NData[0].P = plci->fax_connect_info_buffer;
14208                 plci->NData[0].PLength = plci->fax_connect_info_length;
14209                 plci->NL.X = plci->NData;
14210                 plci->NL.ReqCh = 0;
14211                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14212                 plci->adapter->request(&plci->NL);
14213                 return;
14214         case FAX_CONNECT_INFO_COMMAND_2:
14215                 if ((Rc != OK) && (Rc != OK_FC))
14216                 {
14217                         dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14218                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14219                         Info = _WRONG_STATE;
14220                         break;
14221                 }
14222                 if (plci_nl_busy(plci))
14223                 {
14224                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14225                         return;
14226                 }
14227                 plci->command = _CONNECT_B3_R;
14228                 nl_req_ncci(plci, N_CONNECT, 0);
14229                 send_req(plci);
14230                 return;
14231         }
14232         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233 }
14234
14235
14236 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14237 {
14238         word Info;
14239         word internal_command;
14240
14241         dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14242                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14243
14244         Info = GOOD;
14245         internal_command = plci->internal_command;
14246         plci->internal_command = 0;
14247         switch (internal_command)
14248         {
14249         default:
14250                 plci->command = 0;
14251                 plci->adjust_b_parms_msg = NULL;
14252                 plci->adjust_b_facilities = plci->B1_facilities;
14253                 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14254                 plci->adjust_b_ncci = (word)(Id >> 16);
14255                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14256                 plci->adjust_b_state = ADJUST_B_START;
14257                 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14258                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14259         case FAX_ADJUST_B23_COMMAND_1:
14260                 Info = adjust_b_process(Id, plci, Rc);
14261                 if (Info != GOOD)
14262                 {
14263                         dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14264                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14265                         break;
14266                 }
14267                 if (plci->internal_command)
14268                         return;
14269         case FAX_ADJUST_B23_COMMAND_2:
14270                 if (plci_nl_busy(plci))
14271                 {
14272                         plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14273                         return;
14274                 }
14275                 plci->command = _CONNECT_B3_R;
14276                 nl_req_ncci(plci, N_CONNECT, 0);
14277                 send_req(plci);
14278                 return;
14279         }
14280         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14281 }
14282
14283
14284 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14285 {
14286         word internal_command;
14287
14288         dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14289                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14290
14291         internal_command = plci->internal_command;
14292         plci->internal_command = 0;
14293         switch (internal_command)
14294         {
14295         default:
14296                 plci->command = 0;
14297                 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14298                 return;
14299         case FAX_DISCONNECT_COMMAND_1:
14300         case FAX_DISCONNECT_COMMAND_2:
14301         case FAX_DISCONNECT_COMMAND_3:
14302                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14303                 {
14304                         dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14305                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14306                         break;
14307                 }
14308                 if (Rc == OK)
14309                 {
14310                         if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14311                             || (internal_command == FAX_DISCONNECT_COMMAND_2))
14312                         {
14313                                 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14314                         }
14315                 }
14316                 else if (Rc == 0)
14317                 {
14318                         if (internal_command == FAX_DISCONNECT_COMMAND_1)
14319                                 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14320                 }
14321                 return;
14322         }
14323 }
14324
14325
14326
14327 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14328 {
14329         word Info;
14330         word internal_command;
14331
14332         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14333                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14334
14335         Info = GOOD;
14336         internal_command = plci->internal_command;
14337         plci->internal_command = 0;
14338         switch (internal_command)
14339         {
14340         default:
14341                 plci->command = 0;
14342         case RTP_CONNECT_B3_REQ_COMMAND_1:
14343                 if (plci_nl_busy(plci))
14344                 {
14345                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14346                         return;
14347                 }
14348                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14349                 nl_req_ncci(plci, N_CONNECT, 0);
14350                 send_req(plci);
14351                 return;
14352         case RTP_CONNECT_B3_REQ_COMMAND_2:
14353                 if ((Rc != OK) && (Rc != OK_FC))
14354                 {
14355                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14356                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14357                         Info = _WRONG_STATE;
14358                         break;
14359                 }
14360                 if (plci_nl_busy(plci))
14361                 {
14362                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14363                         return;
14364                 }
14365                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14366                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14367                 plci->NData[0].P = plci->internal_req_buffer + 1;
14368                 plci->NL.X = plci->NData;
14369                 plci->NL.ReqCh = 0;
14370                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14371                 plci->adapter->request(&plci->NL);
14372                 break;
14373         case RTP_CONNECT_B3_REQ_COMMAND_3:
14374                 return;
14375         }
14376         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14377 }
14378
14379
14380 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14381 {
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         internal_command = plci->internal_command;
14388         plci->internal_command = 0;
14389         switch (internal_command)
14390         {
14391         default:
14392                 plci->command = 0;
14393         case RTP_CONNECT_B3_RES_COMMAND_1:
14394                 if (plci_nl_busy(plci))
14395                 {
14396                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14397                         return;
14398                 }
14399                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14400                 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14401                 send_req(plci);
14402                 return;
14403         case RTP_CONNECT_B3_RES_COMMAND_2:
14404                 if ((Rc != OK) && (Rc != OK_FC))
14405                 {
14406                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14407                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14408                         break;
14409                 }
14410                 if (plci_nl_busy(plci))
14411                 {
14412                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14413                         return;
14414                 }
14415                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14416                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14417                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14418                 plci->NData[0].P = plci->internal_req_buffer + 1;
14419                 plci->NL.X = plci->NData;
14420                 plci->NL.ReqCh = 0;
14421                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14422                 plci->adapter->request(&plci->NL);
14423                 return;
14424         case RTP_CONNECT_B3_RES_COMMAND_3:
14425                 return;
14426         }
14427 }
14428
14429
14430
14431 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14432 {
14433         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14434         word Info;
14435         word internal_command;
14436
14437         dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14438                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14439
14440         Info = GOOD;
14441         internal_command = plci->internal_command;
14442         plci->internal_command = 0;
14443         switch (internal_command)
14444         {
14445         default:
14446                 if (!plci->NL.Id)
14447                         break;
14448                 plci->command = 0;
14449                 plci->adjust_b_parms_msg = NULL;
14450                 plci->adjust_b_facilities = plci->B1_facilities;
14451                 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14452                 plci->adjust_b_ncci = (word)(Id >> 16);
14453                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14454                 plci->adjust_b_state = ADJUST_B_START;
14455                 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14456                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14457         case HOLD_SAVE_COMMAND_1:
14458                 Info = adjust_b_process(Id, plci, Rc);
14459                 if (Info != GOOD)
14460                 {
14461                         dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14462                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14463                         break;
14464                 }
14465                 if (plci->internal_command)
14466                         return;
14467         }
14468         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14469 }
14470
14471
14472 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14473 {
14474         byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14475         word Info;
14476         word internal_command;
14477
14478         dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14479                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14480
14481         Info = GOOD;
14482         internal_command = plci->internal_command;
14483         plci->internal_command = 0;
14484         switch (internal_command)
14485         {
14486         default:
14487                 plci->command = 0;
14488                 plci->adjust_b_parms_msg = NULL;
14489                 plci->adjust_b_facilities = plci->B1_facilities;
14490                 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14491                 plci->adjust_b_ncci = (word)(Id >> 16);
14492                 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14493                 plci->adjust_b_state = ADJUST_B_START;
14494                 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14495                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14496         case RETRIEVE_RESTORE_COMMAND_1:
14497                 Info = adjust_b_process(Id, plci, Rc);
14498                 if (Info != GOOD)
14499                 {
14500                         dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14501                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14502                         break;
14503                 }
14504                 if (plci->internal_command)
14505                         return;
14506         }
14507         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14508 }
14509
14510
14511 static void init_b1_config(PLCI *plci)
14512 {
14513
14514         dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14515                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14516                         (char *)(FILE_), __LINE__));
14517
14518         plci->B1_resource = 0;
14519         plci->B1_facilities = 0;
14520
14521         plci->li_bchannel_id = 0;
14522         mixer_clear_config(plci);
14523
14524
14525         ec_clear_config(plci);
14526
14527
14528         dtmf_rec_clear_config(plci);
14529         dtmf_send_clear_config(plci);
14530         dtmf_parameter_clear_config(plci);
14531
14532         adv_voice_clear_config(plci);
14533         adjust_b_clear(plci);
14534 }
14535
14536
14537 static void clear_b1_config(PLCI *plci)
14538 {
14539
14540         dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14541                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14542                         (char *)(FILE_), __LINE__));
14543
14544         adv_voice_clear_config(plci);
14545         adjust_b_clear(plci);
14546
14547         ec_clear_config(plci);
14548
14549
14550         dtmf_rec_clear_config(plci);
14551         dtmf_send_clear_config(plci);
14552         dtmf_parameter_clear_config(plci);
14553
14554
14555         if ((plci->li_bchannel_id != 0)
14556             && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14557         {
14558                 mixer_clear_config(plci);
14559                 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14560                 plci->li_bchannel_id = 0;
14561         }
14562
14563         plci->B1_resource = 0;
14564         plci->B1_facilities = 0;
14565 }
14566
14567
14568 /* -----------------------------------------------------------------
14569    XON protocol local helpers
14570    ----------------------------------------------------------------- */
14571 static void channel_flow_control_remove(PLCI *plci) {
14572         DIVA_CAPI_ADAPTER *a = plci->adapter;
14573         word i;
14574         for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14575                 if (a->ch_flow_plci[i] == plci->Id) {
14576                         a->ch_flow_plci[i] = 0;
14577                         a->ch_flow_control[i] = 0;
14578                 }
14579         }
14580 }
14581
14582 static void channel_x_on(PLCI *plci, byte ch) {
14583         DIVA_CAPI_ADAPTER *a = plci->adapter;
14584         if (a->ch_flow_control[ch] & N_XON_SENT) {
14585                 a->ch_flow_control[ch] &= ~N_XON_SENT;
14586         }
14587 }
14588
14589 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14590         DIVA_CAPI_ADAPTER *a = plci->adapter;
14591         if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14592                 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14593                 a->ch_flow_plci[ch] = plci->Id;
14594                 a->ch_flow_control_pending++;
14595         }
14596 }
14597
14598 static void channel_request_xon(PLCI *plci, byte ch) {
14599         DIVA_CAPI_ADAPTER *a = plci->adapter;
14600
14601         if (a->ch_flow_control[ch] & N_CH_XOFF) {
14602                 a->ch_flow_control[ch] |= N_XON_REQ;
14603                 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14604                 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14605         }
14606 }
14607
14608 static void channel_xmit_extended_xon(PLCI *plci) {
14609         DIVA_CAPI_ADAPTER *a;
14610         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14611         int i, one_requested = 0;
14612
14613         if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14614                 return;
14615         }
14616
14617         for (i = 0; i < max_ch; i++) {
14618                 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14619                     (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14620                     (plci->Id == a->ch_flow_plci[i])) {
14621                         channel_request_xon(plci, (byte)i);
14622                         one_requested = 1;
14623                 }
14624         }
14625
14626         if (one_requested) {
14627                 channel_xmit_xon(plci);
14628         }
14629 }
14630
14631 /*
14632   Try to xmit next X_ON
14633 */
14634 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14635         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14636         int i;
14637
14638         if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14639                 return (0);
14640         }
14641
14642         if (a->last_flow_control_ch >= max_ch) {
14643                 a->last_flow_control_ch = 1;
14644         }
14645         for (i = a->last_flow_control_ch; i < max_ch; i++) {
14646                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14647                     (plci->Id == a->ch_flow_plci[i])) {
14648                         a->last_flow_control_ch = i + 1;
14649                         return (i);
14650                 }
14651         }
14652
14653         for (i = 1; i < a->last_flow_control_ch; i++) {
14654                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14655                     (plci->Id == a->ch_flow_plci[i])) {
14656                         a->last_flow_control_ch = i + 1;
14657                         return (i);
14658                 }
14659         }
14660
14661         return (0);
14662 }
14663
14664 static void channel_xmit_xon(PLCI *plci) {
14665         DIVA_CAPI_ADAPTER *a = plci->adapter;
14666         byte ch;
14667
14668         if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14669                 return;
14670         }
14671         if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14672                 return;
14673         }
14674         a->ch_flow_control[ch] &= ~N_XON_REQ;
14675         a->ch_flow_control[ch] |= N_XON_SENT;
14676
14677         plci->NL.Req = plci->nl_req = (byte)N_XON;
14678         plci->NL.ReqCh         = ch;
14679         plci->NL.X             = plci->NData;
14680         plci->NL.XNum          = 1;
14681         plci->NData[0].P       = &plci->RBuffer[0];
14682         plci->NData[0].PLength = 0;
14683
14684         plci->adapter->request(&plci->NL);
14685 }
14686
14687 static int channel_can_xon(PLCI *plci, byte ch) {
14688         APPL *APPLptr;
14689         DIVA_CAPI_ADAPTER *a;
14690         word NCCIcode;
14691         dword count;
14692         word Num;
14693         word i;
14694
14695         APPLptr = plci->appl;
14696         a = plci->adapter;
14697
14698         if (!APPLptr)
14699                 return (0);
14700
14701         NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14702
14703         /* count all buffers within the Application pool    */
14704         /* belonging to the same NCCI. XON if a first is    */
14705         /* used.                                            */
14706         count = 0;
14707         Num = 0xffff;
14708         for (i = 0; i < APPLptr->MaxBuffer; i++) {
14709                 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14710                 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14711         }
14712         if ((count > 2) || (Num == 0xffff)) {
14713                 return (0);
14714         }
14715         return (1);
14716 }
14717
14718
14719 /*------------------------------------------------------------------*/
14720
14721 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14722 {
14723         return 1;
14724 }
14725
14726
14727
14728 /**********************************************************************************/
14729 /* function groups the listening applications according to the CIP mask and the   */
14730 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14731 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14732 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14733 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14734 /* OS specific part (per adapter).                                                */
14735 /**********************************************************************************/
14736 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14737 {
14738         word i, j, k, busy, group_found;
14739         dword info_mask_group[MAX_CIP_TYPES];
14740         dword cip_mask_group[MAX_CIP_TYPES];
14741         word appl_number_group_type[MAX_APPL];
14742         PLCI *auxplci;
14743
14744         set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14745
14746         if (!a->group_optimization_enabled)
14747         {
14748                 dbug(1, dprintf("No group optimization"));
14749                 return;
14750         }
14751
14752         dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14753
14754         for (i = 0; i < MAX_CIP_TYPES; i++)
14755         {
14756                 info_mask_group[i] = 0;
14757                 cip_mask_group[i] = 0;
14758         }
14759         for (i = 0; i < MAX_APPL; i++)
14760         {
14761                 appl_number_group_type[i] = 0;
14762         }
14763         for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14764         {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14765                 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14766                 {
14767                         dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14768                         return; /* allow good application unfiltered access */
14769                 }
14770         }
14771         for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14772         {
14773                 if (application[i].Id && a->CIP_Mask[i])
14774                 {
14775                         for (k = 0, busy = false; k < a->max_plci; k++)
14776                         {
14777                                 if (a->plci[k].Id)
14778                                 {
14779                                         auxplci = &a->plci[k];
14780                                         if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14781                                         {
14782                                                 busy = true;
14783                                                 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14784                                         }
14785                                         else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14786                                         {
14787                                                 busy = true;
14788                                                 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14789                                         }
14790                                 }
14791                         }
14792
14793                         for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14794                         {
14795                                 if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14796                                 {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14797                                         appl_number_group_type[i] = MAX_CIP_TYPES;
14798                                         group_found = true;
14799                                         dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14800                                 }
14801                                 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14802                                 {                                      /* is group already present ?                  */
14803                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14804                                         group_found = true;
14805                                         dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14806                                 }
14807                                 else if (!info_mask_group[j])
14808                                 {                                      /* establish a new group                       */
14809                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14810                                         info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14811                                         cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14812                                         group_found = true;
14813                                         dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14814                                 }
14815                         }
14816                 }
14817         }
14818
14819         for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14820         {
14821                 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14822                 {
14823                         if (appl_number_group_type[i] == MAX_CIP_TYPES)
14824                         {
14825                                 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14826                         }
14827                         else
14828                         {
14829                                 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14830                                 for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14831                                 {
14832                                         if (appl_number_group_type[i] == appl_number_group_type[j])
14833                                         {
14834                                                 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14835                                                 clear_group_ind_mask_bit(plci, j);           /* disable call on other group members */
14836                                                 appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14837                                         }
14838                                 }
14839                         }
14840                 }
14841                 else                                                 /* application should not get a call */
14842                 {
14843                         clear_group_ind_mask_bit(plci, i);
14844                 }
14845         }
14846
14847 }
14848
14849
14850
14851 /* OS notifies the driver about a application Capi_Register */
14852 word CapiRegister(word id)
14853 {
14854         word i, j, appls_found;
14855
14856         PLCI *plci;
14857         DIVA_CAPI_ADAPTER *a;
14858
14859         for (i = 0, appls_found = 0; i < max_appl; i++)
14860         {
14861                 if (application[i].Id && (application[i].Id != id))
14862                 {
14863                         appls_found++;                       /* an application has been found */
14864                 }
14865         }
14866
14867         if (appls_found) return true;
14868         for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14869         {
14870                 a = &adapter[i];
14871                 if (a->request)
14872                 {
14873                         if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14874                         {
14875                                 if (!appls_found)           /* first application does a capi register   */
14876                                 {
14877                                         if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14878                                         {
14879                                                 plci = &a->plci[j - 1];
14880                                                 plci->command = 0;
14881                                                 add_p(plci, OAD, "\x01\xfd");
14882                                                 add_p(plci, CAI, "\x01\x80");
14883                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14884                                                 add_p(plci, SHIFT | 6, NULL);
14885                                                 add_p(plci, SIN, "\x02\x00\x00");
14886                                                 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14887                                                 sig_req(plci, ASSIGN, DSIG_ID);
14888                                                 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14889                                                 sig_req(plci, SIG_CTRL, 0);
14890                                                 send_req(plci);
14891                                         }
14892                                 }
14893                         }
14894                 }
14895         }
14896         return false;
14897 }
14898
14899 /*------------------------------------------------------------------*/
14900
14901 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14902
14903 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14904 {
14905         word i;
14906         /* Format of vswitch_t:
14907            0 byte length
14908            1 byte VSWITCHIE
14909            2 byte VSWITCH_REQ/VSWITCH_IND
14910            3 byte reserved
14911            4 word VSwitchcommand
14912            6 word returnerror
14913            8... Params
14914         */
14915         if (!plci ||
14916             !plci->appl ||
14917             !plci->State ||
14918             plci->Sig.Ind == NCR_FACILITY
14919                 )
14920                 return;
14921
14922         for (i = 0; i < MAX_MULTI_IE; i++)
14923         {
14924                 if (!parms[i][0]) continue;
14925                 if (parms[i][0] < 7)
14926                 {
14927                         parms[i][0] = 0; /* kill it */
14928                         continue;
14929                 }
14930                 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14931                 switch (parms[i][4])
14932                 {
14933                 case VSJOIN:
14934                         if (!plci->relatedPTYPLCI ||
14935                             (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14936                         { /* Error */
14937                                 break;
14938                         }
14939                         /* remember all necessary informations */
14940                         if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14941                         {
14942                                 break;
14943                         }
14944                         if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14945                         {   /* first indication after ECT-Request on Consultation Call */
14946                                 plci->vswitchstate = parms[i][9];
14947                                 parms[i][9] = 2; /* State */
14948                                 /* now ask first Call to join */
14949                         }
14950                         else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14951                         { /* Answer of VSWITCH_REQ from first Call */
14952                                 plci->vswitchstate = parms[i][9];
14953                                 /* tell consultation call to join
14954                                    and the protocol capabilities of the first call */
14955                         }
14956                         else
14957                         { /* Error */
14958                                 break;
14959                         }
14960                         plci->vsprot = parms[i][10]; /* protocol */
14961                         plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14962                         /* send join request to related PLCI */
14963                         parms[i][1] = VSWITCHIE;
14964                         parms[i][2] = VSWITCH_REQ;
14965
14966                         plci->relatedPTYPLCI->command = 0;
14967                         plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14968                         add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14969                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14970                         send_req(plci->relatedPTYPLCI);
14971                         break;
14972                 case VSTRANSPORT:
14973                 default:
14974                         if (plci->relatedPTYPLCI &&
14975                             plci->vswitchstate == 3 &&
14976                             plci->relatedPTYPLCI->vswitchstate == 3)
14977                         {
14978                                 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14979                                 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14980                                 send_req(plci->relatedPTYPLCI);
14981                         }
14982                         break;
14983                 }
14984                 parms[i][0] = 0; /* kill it */
14985         }
14986 }
14987
14988
14989 /*------------------------------------------------------------------*/
14990
14991 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14992         ENTITY e;
14993         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14994
14995         if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14996                 return (-1);
14997         }
14998
14999         pReq->xdi_dma_descriptor_operation.Req = 0;
15000         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15001
15002         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15003         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15004         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15005         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15006
15007         e.user[0] = plci->adapter->Id - 1;
15008         plci->adapter->request((ENTITY *)pReq);
15009
15010         if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15011             (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15012             pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15013                 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15014                 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15015                                 plci->adapter->Id,
15016                                 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15017                                 *dma_magic));
15018                 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15019         } else {
15020                 dbug(1, dprintf("dma_alloc failed"));
15021                 return (-1);
15022         }
15023 }
15024
15025 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15026         ENTITY e;
15027         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15028
15029         if (nr < 0) {
15030                 return;
15031         }
15032
15033         pReq->xdi_dma_descriptor_operation.Req = 0;
15034         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15035
15036         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15037         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15038         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15039         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15040
15041         e.user[0] = plci->adapter->Id - 1;
15042         plci->adapter->request((ENTITY *)pReq);
15043
15044         if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15045                 dbug(1, dprintf("dma_free(%d)", nr));
15046         } else {
15047                 dbug(1, dprintf("dma_free failed (%d)", nr));
15048         }
15049 }
15050
15051 /*------------------------------------------------------------------*/