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 
api_put(APPL * appl,CAPI_MSG * msg)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 
api_parse(byte * msg,word length,byte * format,API_PARSE * parms)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 
api_save_msg(API_PARSE * in,byte * format,API_SAVE * out)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 
api_load_msg(API_SAVE * in,API_PARSE * out)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 
api_remove_start(void)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 
init_internal_command_queue(PLCI * plci)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 
start_internal_command(dword Id,PLCI * plci,t_std_internal_command command_function)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 
next_internal_command(dword Id,PLCI * plci)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 
get_ncci(PLCI * plci,byte ch,word force_ncci)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 
ncci_free_receive_buffers(PLCI * plci,word ncci)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 
cleanup_ncci_data(PLCI * plci,word ncci)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 
ncci_remove(PLCI * plci,word ncci,byte preserve_ncci)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 
plci_free_msg_in_queue(PLCI * plci)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 
plci_remove(PLCI * plci)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 
set_group_ind_mask(PLCI * plci)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 
clear_group_ind_mask_bit(PLCI * plci,word b)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 
test_group_ind_mask_bit(PLCI * plci,word b)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 
clear_c_ind_mask(PLCI * plci)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 
c_ind_mask_empty(PLCI * plci)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 
set_c_ind_mask_bit(PLCI * plci,word b)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 
clear_c_ind_mask_bit(PLCI * plci,word b)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 
test_c_ind_mask_bit(PLCI * plci,word b)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 
dump_c_ind_mask(PLCI * plci)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 
connect_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
connect_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
connect_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
disconnect_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
disconnect_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
listen_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
info_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
info_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
alert_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
facility_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
facility_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
connect_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
connect_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
connect_b3_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
disconnect_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
disconnect_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
data_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
data_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
reset_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
reset_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
connect_b3_t90_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
select_b_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
manufacturer_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)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 
manufacturer_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
callback(ENTITY * e)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 
control_rc(PLCI * plci,byte req,byte rc,byte ch,byte global_req,byte nl_rc)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 
data_rc(PLCI * plci,byte ch)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 
data_ack(PLCI * plci,byte ch)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 
sig_ind(PLCI * plci)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\0x00\0x00\0x00\0x00";
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 
SendSetupInfo(APPL * appl,PLCI * plci,dword Id,byte ** parms,byte Info_Sent_Flag)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 
SendInfo(PLCI * plci,dword Id,byte ** parms,byte iesent)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 
SendMultiIE(PLCI * plci,dword Id,byte ** parms,byte ie_type,dword info_mask,byte setupParse)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 
SendSSExtInd(APPL * appl,PLCI * plci,dword Id,byte ** parms)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 
nl_ind(PLCI * plci)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 
get_plci(DIVA_CAPI_ADAPTER * a)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 
add_p(PLCI * plci,byte code,byte * p)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 /*------------------------------------------------------------------*/
add_s(PLCI * plci,byte code,API_PARSE * p)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 /*------------------------------------------------------------------*/
add_ss(PLCI * plci,byte code,API_PARSE * p)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 /*------------------------------------------------------------------*/
getChannel(API_PARSE * p)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 
add_ie(PLCI * plci,byte code,byte * p,word p_length)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 
add_d(PLCI * plci,word length,byte * p)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 
add_ai(PLCI * plci,API_PARSE * ai)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 
add_b1(PLCI * plci,API_PARSE * bp,word b_channel_info,word b1_facilities)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 
add_b23(PLCI * plci,API_PARSE * bp)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 /*----------------------------------------------------------------*/
add_modem_b23(PLCI * plci,API_PARSE * bp_parms)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 
sig_req(PLCI * plci,byte req,byte Id)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 
nl_req_ncci(PLCI * plci,byte req,byte ncci)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 
send_req(PLCI * plci)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 
send_data(PLCI * plci)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 
listen_check(DIVA_CAPI_ADAPTER * a)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 
IndParse(PLCI * plci,word * parms_id,byte ** parms,byte multiIEsize)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 
ie_compare(byte * ie1,byte * ie2)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 
find_cip(DIVA_CAPI_ADAPTER * a,byte * bc,byte * hlc)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 
AddInfo(byte ** add_i,byte ** fty_i,byte * esc_chi,byte * facility)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 
SetVoiceChannel(PLCI * plci,byte * chi,DIVA_CAPI_ADAPTER * a)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 
VoiceChannelOff(PLCI * plci)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 
AdvCodecSupport(DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,byte hook_listen)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 
CodecIdCheck(DIVA_CAPI_ADAPTER * a,PLCI * plci)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    ------------------------------------------------------------------- */
diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER * a,IDI_SYNC_REQ * preq)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    ------------------------------------------------------------------- */
diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER * a)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 */
AutomaticLaw(DIVA_CAPI_ADAPTER * a)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 */
CapiRelease(word Id)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 
plci_remove_check(PLCI * plci)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 
plci_nl_busy(PLCI * plci)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 
dtmf_enable_receiver(PLCI * plci,byte enable_mask)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 
dtmf_send_digits(PLCI * plci,byte * digit_buffer,word digit_count)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 
dtmf_rec_clear_config(PLCI * plci)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 
dtmf_send_clear_config(PLCI * plci)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 
dtmf_prepare_switch(dword Id,PLCI * plci)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 
dtmf_save_config(dword Id,PLCI * plci,byte Rc)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 
dtmf_restore_config(dword Id,PLCI * plci,byte Rc)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 
dtmf_command(dword Id,PLCI * plci,byte Rc)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 
dtmf_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
dtmf_confirmation(dword Id,PLCI * plci)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 
dtmf_indication(dword Id,PLCI * plci,byte * msg,word length)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 
dtmf_parameter_write(PLCI * plci)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 
dtmf_parameter_clear_config(PLCI * plci)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 
dtmf_parameter_prepare_switch(dword Id,PLCI * plci)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 
dtmf_parameter_save_config(dword Id,PLCI * plci,byte Rc)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 
dtmf_parameter_restore_config(dword Id,PLCI * plci,byte Rc)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 
chi_to_channel(byte * chi,dword * pchannelmap)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 
mixer_set_bchannel_id_esc(PLCI * plci,byte bchannel_id)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 
mixer_set_bchannel_id(PLCI * plci,byte * chi)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 
mixer_calculate_coefs(DIVA_CAPI_ADAPTER * a)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 
xconnect_query_addresses(PLCI * plci)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 
xconnect_write_coefs(PLCI * plci,word internal_command)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 
xconnect_write_coefs_process(dword Id,PLCI * plci,byte Rc)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 
mixer_notify_update(PLCI * plci,byte others)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 
mixer_clear_config(PLCI * plci)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 
mixer_prepare_switch(dword Id,PLCI * plci)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 
mixer_save_config(dword Id,PLCI * plci,byte Rc)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 
mixer_restore_config(dword Id,PLCI * plci,byte Rc)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 
mixer_command(dword Id,PLCI * plci,byte Rc)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 
li_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)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 
li2_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)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 
li_check_main_plci(dword Id,PLCI * plci)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 
li_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)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 
li2_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)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 
mixer_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
mixer_indication_coefs_set(dword Id,PLCI * plci)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 
mixer_indication_xconnect_from(dword Id,PLCI * plci,byte * msg,word length)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 
mixer_indication_xconnect_to(dword Id,PLCI * plci,byte * msg,word length)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 
mixer_notify_source_removed(PLCI * plci,dword plci_b_id)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 
mixer_remove(PLCI * plci)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 
ec_write_parameters(PLCI * plci)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 
ec_clear_config(PLCI * plci)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 
ec_prepare_switch(dword Id,PLCI * plci)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 
ec_save_config(dword Id,PLCI * plci,byte Rc)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 
ec_restore_config(dword Id,PLCI * plci,byte Rc)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 
ec_command(dword Id,PLCI * plci,byte Rc)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 
ec_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)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 
ec_indication(dword Id,PLCI * plci,byte * msg,word length)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 
adv_voice_write_coefs(PLCI * plci,word write_command)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 
adv_voice_clear_config(PLCI * plci)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 
adv_voice_prepare_switch(dword Id,PLCI * plci)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 
adv_voice_save_config(dword Id,PLCI * plci,byte Rc)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 
adv_voice_restore_config(dword Id,PLCI * plci,byte Rc)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 
get_b1_facilities(PLCI * plci,byte b1_resource)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 
add_b1_facilities(PLCI * plci,byte b1_resource,word b1_facilities)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 
adjust_b1_facilities(PLCI * plci,byte new_b1_resource,word new_b1_facilities)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 
adjust_b_clear(PLCI * plci)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 
adjust_b_process(dword Id,PLCI * plci,byte Rc)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 
adjust_b1_resource(dword Id,PLCI * plci,API_SAVE * bp_msg,word b1_facilities,word internal_command)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 
adjust_b_restore(dword Id,PLCI * plci,byte Rc)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 
reset_b3_command(dword Id,PLCI * plci,byte Rc)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 
select_b_command(dword Id,PLCI * plci,byte Rc)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 
fax_connect_ack_command(dword Id,PLCI * plci,byte Rc)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 
fax_edata_ack_command(dword Id,PLCI * plci,byte Rc)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 
fax_connect_info_command(dword Id,PLCI * plci,byte Rc)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 
fax_adjust_b23_command(dword Id,PLCI * plci,byte Rc)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 
fax_disconnect_command(dword Id,PLCI * plci,byte Rc)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 
rtp_connect_b3_req_command(dword Id,PLCI * plci,byte Rc)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 
rtp_connect_b3_res_command(dword Id,PLCI * plci,byte Rc)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 
hold_save_command(dword Id,PLCI * plci,byte Rc)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 
retrieve_restore_command(dword Id,PLCI * plci,byte Rc)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 
init_b1_config(PLCI * plci)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 
clear_b1_config(PLCI * plci)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    ----------------------------------------------------------------- */
channel_flow_control_remove(PLCI * plci)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 
channel_x_on(PLCI * plci,byte ch)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 
channel_x_off(PLCI * plci,byte ch,byte flag)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 
channel_request_xon(PLCI * plci,byte ch)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 
channel_xmit_extended_xon(PLCI * plci)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   */
find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER * a,PLCI * plci)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 
channel_xmit_xon(PLCI * plci)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 
channel_can_xon(PLCI * plci,byte ch)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 
CPN_filter_ok(byte * cpn,DIVA_CAPI_ADAPTER * a,word offset)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 /**********************************************************************************/
group_optimization(DIVA_CAPI_ADAPTER * a,PLCI * plci)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 */
CapiRegister(word id)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 
VSwitchReqInd(PLCI * plci,dword Id,byte ** parms)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 
diva_get_dma_descriptor(PLCI * plci,dword * dma_magic)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 
diva_free_dma_descriptor(PLCI * plci,int nr)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 /*------------------------------------------------------------------*/
15052