Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *
  3   Copyright (c) Eicon Networks, 2002.
  4  *
  5   This source file is supplied for the use with
  6   Eicon Networks range of DIVA Server Adapters.
  7  *
  8   Eicon File Revision :    2.1
  9  *
 10   This program is free software; you can redistribute it and/or modify
 11   it under the terms of the GNU General Public License as published by
 12   the Free Software Foundation; either version 2, or (at your option)
 13   any later version.
 14  *
 15   This program is distributed in the hope that it will be useful,
 16   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
 17   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 18   See the GNU General Public License for more details.
 19  *
 20   You should have received a copy of the GNU General Public License
 21   along with this program; if not, write to the Free Software
 22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 23  *
 24  */
 25 
 26 
 27 
 28 
 29 
 30 #include "platform.h"
 31 #include "di_defs.h"
 32 #include "pc.h"
 33 #include "capi20.h"
 34 #include "divacapi.h"
 35 #include "mdm_msg.h"
 36 #include "divasync.h"
 37 
 38 
 39 
 40 #define FILE_ "MESSAGE.C"
 41 #define dprintf
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 /*------------------------------------------------------------------*/
 52 /* This is options supported for all adapters that are server by    */
 53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
 54 /* and it is not necessary to save it separate for every adapter    */
 55 /* Macrose defined here have only local meaning                     */
 56 /*------------------------------------------------------------------*/
 57 static dword diva_xdi_extended_features = 0;
 58 
 59 #define DIVA_CAPI_USE_CMA                 0x00000001
 60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
 61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
 62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
 63 
 64 /*
 65   CAPI can request to process all return codes self only if:
 66   protocol code supports this && xdi supports this
 67  */
 68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
 69 
 70 /*------------------------------------------------------------------*/
 71 /* local function prototypes                                        */
 72 /*------------------------------------------------------------------*/
 73 
 74 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
 75 static void set_group_ind_mask (PLCI   *plci);
 76 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
 77 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
 78 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
 79 word CapiRelease(word);
 80 word CapiRegister(word);
 81 word api_put(APPL   *, CAPI_MSG   *);
 82 static word api_parse(byte   *, word, byte *, API_PARSE *);
 83 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
 84 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
 85 
 86 word api_remove_start(void);
 87 void api_remove_complete(void);
 88 
 89 static void plci_remove(PLCI   *);
 90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
 91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
 92 
 93 void   callback(ENTITY   *);
 94 
 95 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
 96 static void data_rc(PLCI   *, byte);
 97 static void data_ack(PLCI   *, byte);
 98 static void sig_ind(PLCI   *);
 99 static void SendInfo(PLCI   *, dword, byte   * *, byte);
100 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
101 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
102 
103 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
104 
105 static void nl_ind(PLCI   *);
106 
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131 
132 static word get_plci(DIVA_CAPI_ADAPTER   *);
133 static void add_p(PLCI   *, byte, byte   *);
134 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
137 static void add_d(PLCI   *, word, byte   *);
138 static void add_ai(PLCI   *, API_PARSE *);
139 static word add_b1(PLCI   *, API_PARSE *, word, word);
140 static word add_b23(PLCI   *, API_PARSE *);
141 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI   *, byte, byte);
143 static void nl_req_ncci(PLCI   *, byte, byte);
144 static void send_req(PLCI   *);
145 static void send_data(PLCI   *);
146 static word plci_remove_check(PLCI   *);
147 static void listen_check(DIVA_CAPI_ADAPTER   *);
148 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI   *, word *, byte   **, byte);
151 static byte ie_compare(byte   *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
153 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
154 
155 /*
156   XON protocol helpers
157   */
158 static void channel_flow_control_remove (PLCI   * plci);
159 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI   * plci, byte ch);
161 static void channel_request_xon (PLCI   * plci, byte ch);
162 static void channel_xmit_xon (PLCI   * plci);
163 static int channel_can_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI   * plci);
165 
166 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
169 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
170 static void VoiceChannelOff(PLCI   *plci);
171 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
172 static void adv_voice_clear_config (PLCI   *plci);
173 
174 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
189 static void init_b1_config (PLCI   *plci);
190 static void clear_b1_config (PLCI   *plci);
191 
192 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI   *plci);
195 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
196 static void dtmf_parameter_write (PLCI   *plci);
197 
198 
199 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
201 static void mixer_clear_config (PLCI   *plci);
202 static void mixer_notify_update (PLCI   *plci, byte others);
203 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_remove (PLCI   *plci);
209 
210 
211 static void ec_command (dword Id, PLCI   *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
214 
215 
216 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
218 
219 
220 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
221 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
222 
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226 
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231 
232 void   sendf(APPL   *, word, dword, word, byte *, ...);
233 void   * TransmitBufferSet(APPL   * appl, dword ref);
234 void   * TransmitBufferGet(APPL   * appl, void   * p);
235 void TransmitBufferFree(APPL   * appl, void   * p);
236 void   * ReceiveBufferGet(APPL   * appl, int Num);
237 
238 int fax_head_line_time (char *buffer);
239 
240 
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER   * adapter;
247 extern APPL   * application;
248 
249 
250 
251 
252 
253 
254 
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257 
258 
259 static struct _ftable {
260   word command;
261   byte * format;
262   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
263 } ftable[] = {
264   {_DATA_B3_R,                          "dwww",         data_b3_req},
265   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
266   {_INFO_R,                             "ss",           info_req},
267   {_INFO_I|RESPONSE,                    "",             info_res},
268   {_CONNECT_R,                          "wsssssssss",   connect_req},
269   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
270   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
271   {_DISCONNECT_R,                       "s",            disconnect_req},
272   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
273   {_LISTEN_R,                           "dddss",        listen_req},
274   {_ALERT_R,                            "s",            alert_req},
275   {_FACILITY_R,                         "ws",           facility_req},
276   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
277   {_CONNECT_B3_R,                       "s",            connect_b3_req},
278   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
279   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
280   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
282   {_RESET_B3_R,                         "s",            reset_b3_req},
283   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
284   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
286   {_SELECT_B_REQ,                       "s",            select_b_req},
287   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
289   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
290 };
291 
292 static byte * cip_bc[29][2] = {
293   { "",                     ""                     }, /* 0 */
294   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303   { "",                     ""                     }, /* 10 */
304   { "",                     ""                     }, /* 11 */
305   { "",                     ""                     }, /* 12 */
306   { "",                     ""                     }, /* 13 */
307   { "",                     ""                     }, /* 14 */
308   { "",                     ""                     }, /* 15 */
309 
310   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324 
325 static byte * cip_hlc[29] = {
326   "",                           /* 0 */
327   "",                           /* 1 */
328   "",                           /* 2 */
329   "",                           /* 3 */
330   "",                           /* 4 */
331   "",                           /* 5 */
332   "",                           /* 6 */
333   "",                           /* 7 */
334   "",                           /* 8 */
335   "",                           /* 9 */
336   "",                           /* 10 */
337   "",                           /* 11 */
338   "",                           /* 12 */
339   "",                           /* 13 */
340   "",                           /* 14 */
341   "",                           /* 15 */
342 
343   "\x02\x91\x81",               /* 16 */
344   "\x02\x91\x84",               /* 17 */
345   "\x02\x91\xa1",               /* 18 */
346   "\x02\x91\xa4",               /* 19 */
347   "\x02\x91\xa8",               /* 20 */
348   "\x02\x91\xb1",               /* 21 */
349   "\x02\x91\xb2",               /* 22 */
350   "\x02\x91\xb5",               /* 23 */
351   "\x02\x91\xb8",               /* 24 */
352   "\x02\x91\xc1",               /* 25 */
353   "\x02\x91\x81",               /* 26 */
354   "\x03\x91\xe0\x01",           /* 27 */
355   "\x03\x91\xe0\x02"            /* 28 */
356 };
357 
358 /*------------------------------------------------------------------*/
359 
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366 
367 static byte v120_default_header[] =
368 {
369 
370   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371 
372 };
373 
374 static byte v120_break_header[] =
375 {
376 
377   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378 
379 };
380 
381 
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385 
386 word api_put(APPL   * appl, CAPI_MSG   * msg)
387 {
388   word i, j, k, l, n;
389   word ret;
390   byte c;
391   byte controller;
392   DIVA_CAPI_ADAPTER   * a;
393   PLCI   * plci;
394   NCCI   * ncci_ptr;
395   word ncci;
396   CAPI_MSG   *m;
397     API_PARSE msg_parms[MAX_MSG_PARMS+1];
398 
399   if (msg->header.length < sizeof (msg->header) ||
400       msg->header.length > MAX_MSG_SIZE) {
401     dbug(1,dprintf("bad len"));
402     return _BAD_MSG;
403   }
404 
405   controller = (byte)((msg->header.controller &0x7f)-1);
406 
407   /* controller starts with 0 up to (max_adapter - 1) */
408   if ( controller >= max_adapter )
409   {
410     dbug(1,dprintf("invalid ctrl"));
411     return _BAD_MSG;
412   }
413   
414   a = &adapter[controller];
415   plci = NULL;
416   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417   {
418     dbug(1,dprintf("plci=%x",msg->header.plci));
419     plci = &a->plci[msg->header.plci-1];
420     ncci = GET_WORD(&msg->header.ncci);
421     if (plci->Id
422      && (plci->appl
423       || (plci->State == INC_CON_PENDING)
424       || (plci->State == INC_CON_ALERT)
425       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426      && ((ncci == 0)
427       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429     {
430       i = plci->msg_in_read_pos;
431       j = plci->msg_in_write_pos;
432       if (j >= i)
433       {
434         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435           i += MSG_IN_QUEUE_SIZE - j;
436         else
437           j = 0;
438       }
439       else
440       {
441 
442         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443 
444         if (i > MSG_IN_QUEUE_SIZE - n)
445           i = MSG_IN_QUEUE_SIZE - n + 1;
446         i -= j;
447       }
448 
449       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450 
451       {
452         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453           msg->header.length, plci->msg_in_write_pos,
454           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455 
456         return _QUEUE_FULL;
457       }
458       c = false;
459       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
460        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461       {
462         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463           c = true;
464       }
465       if (msg->header.command == _DATA_B3_R)
466       {
467         if (msg->header.length < 20)
468         {
469           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470           return _BAD_MSG;
471         }
472         ncci_ptr = &(a->ncci[ncci]);
473         n = ncci_ptr->data_pending;
474         l = ncci_ptr->data_ack_pending;
475         k = plci->msg_in_read_pos;
476         while (k != plci->msg_in_write_pos)
477         {
478           if (k == plci->msg_in_wrap_pos)
479             k = 0;
480           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482           {
483             n++;
484             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485               l++;
486           }
487 
488           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
489             MSG_IN_OVERHEAD + 3) & 0xfffc;
490 
491         }
492         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493         {
494           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496 
497           return _QUEUE_FULL;
498         }
499         if (plci->req_in || plci->internal_command)
500         {
501           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
502            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503           {
504             dbug(0,dprintf("Q-FULL3(requeue)"));
505 
506             return _QUEUE_FULL;
507           }
508           c = true;
509         }
510       }
511       else
512       {
513         if (plci->req_in || plci->internal_command)
514           c = true;
515         else
516         {
517           plci->command = msg->header.command;
518           plci->number = msg->header.number;
519         }
520       }
521       if (c)
522       {
523         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524           msg->header.command, plci->req_in, plci->internal_command,
525           msg->header.length, plci->msg_in_write_pos,
526           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527         if (j == 0)
528           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
530         for (i = 0; i < msg->header.length; i++)
531           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
532         if (m->header.command == _DATA_B3_R)
533         {
534 
535           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
536 
537         }
538 
539         j = (j + 3) & 0xfffc;
540 
541         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
542         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543         return 0;
544       }
545     }
546     else
547     {
548       plci = NULL;
549     }
550   }
551   dbug(1,dprintf("com=%x",msg->header.command));
552 
553   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554   for(i=0, ret = _BAD_MSG;
555       i<(sizeof(ftable)/sizeof(struct _ftable));
556       i++) {
557 
558     if(ftable[i].command==msg->header.command) {
559       /* break loop if the message is correct, otherwise continue scan  */
560       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
561       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
562         ret = 0;
563         break;
564       }
565       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
566     }
567   }
568   if(ret) {
569     dbug(1,dprintf("BAD_MSG"));
570     if(plci) plci->command = 0;
571     return ret;
572   }
573 
574 
575   c = ftable[i].function(GET_DWORD(&msg->header.controller),
576                          msg->header.number,
577                          a,
578                          plci,
579                          appl,
580                          msg_parms);
581 
582   channel_xmit_extended_xon (plci);
583 
584   if(c==1) send_req(plci);
585   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
586   if(plci && !plci->req_in) plci->command = 0;
587   return 0;
588 }
589 
590 
591 /*------------------------------------------------------------------*/
592 /* api_parse function, check the format of api messages             */
593 /*------------------------------------------------------------------*/
594 
595 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
596 {
597   word i;
598   word p;
599 
600   for(i=0,p=0; format[i]; i++) {
601     if(parms)
602     {
603       parms[i].info = &msg[p];
604     }
605     switch(format[i]) {
606     case 'b':
607       p +=1;
608       break;
609     case 'w':
610       p +=2;
611       break;
612     case 'd':
613       p +=4;
614       break;
615     case 's':
616       if(msg[p]==0xff) {
617         parms[i].info +=2;
618         parms[i].length = msg[p+1] + (msg[p+2]<<8);
619         p +=(parms[i].length +3);
620       }
621       else {
622         parms[i].length = msg[p];
623         p +=(parms[i].length +1);
624       }
625       break;
626     }
627 
628     if(p>length) return true;
629   }
630   if(parms) parms[i].info = NULL;
631   return false;
632 }
633 
634 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
635 {
636   word i, j, n = 0;
637   byte   *p;
638 
639   p = out->info;
640   for (i = 0; format[i] != '\0'; i++)
641   {
642     out->parms[i].info = p;
643     out->parms[i].length = in[i].length;
644     switch (format[i])
645     {
646     case 'b':
647       n = 1;
648       break;
649     case 'w':
650       n = 2;
651       break;
652     case 'd':
653       n = 4;
654       break;
655     case 's':
656       n = in[i].length + 1;
657       break;
658     }
659     for (j = 0; j < n; j++)
660       *(p++) = in[i].info[j];
661   }
662   out->parms[i].info = NULL;
663   out->parms[i].length = 0;
664 }
665 
666 static void api_load_msg(API_SAVE *in, API_PARSE *out)
667 {
668   word i;
669 
670   i = 0;
671   do
672   {
673     out[i].info = in->parms[i].info;
674     out[i].length = in->parms[i].length;
675   } while (in->parms[i++].info);
676 }
677 
678 
679 /*------------------------------------------------------------------*/
680 /* CAPI remove function                                             */
681 /*------------------------------------------------------------------*/
682 
683 word api_remove_start(void)
684 {
685   word i;
686   word j;
687 
688   if(!remove_started) {
689     remove_started = true;
690     for(i=0;i<max_adapter;i++) {
691       if(adapter[i].request) {
692         for(j=0;j<adapter[i].max_plci;j++) {
693           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
694         }
695       }
696     }
697     return 1;
698   }
699   else {
700     for(i=0;i<max_adapter;i++) {
701       if(adapter[i].request) {
702         for(j=0;j<adapter[i].max_plci;j++) {
703           if(adapter[i].plci[j].Sig.Id) return 1;
704         }
705       }
706     }
707   }
708   api_remove_complete();
709   return 0;
710 }
711 
712 
713 /*------------------------------------------------------------------*/
714 /* internal command queue                                           */
715 /*------------------------------------------------------------------*/
716 
717 static void init_internal_command_queue (PLCI   *plci)
718 {
719   word i;
720 
721   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
722     (char   *)(FILE_), __LINE__));
723 
724   plci->internal_command = 0;
725   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
726     plci->internal_command_queue[i] = NULL;
727 }
728 
729 
730 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
731 {
732   word i;
733 
734   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
735     UnMapId (Id), (char   *)(FILE_), __LINE__));
736 
737   if (plci->internal_command == 0)
738   {
739     plci->internal_command_queue[0] = command_function;
740     (* command_function)(Id, plci, OK);
741   }
742   else
743   {
744     i = 1;
745     while (plci->internal_command_queue[i] != NULL)
746       i++;
747     plci->internal_command_queue[i] = command_function;
748   }
749 }
750 
751 
752 static void next_internal_command (dword Id, PLCI   *plci)
753 {
754   word i;
755 
756   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
757     UnMapId (Id), (char   *)(FILE_), __LINE__));
758 
759   plci->internal_command = 0;
760   plci->internal_command_queue[0] = NULL;
761   while (plci->internal_command_queue[1] != NULL)
762   {
763     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
764       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
765     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
766     (*(plci->internal_command_queue[0]))(Id, plci, OK);
767     if (plci->internal_command != 0)
768       return;
769     plci->internal_command_queue[0] = NULL;
770   }
771 }
772 
773 
774 /*------------------------------------------------------------------*/
775 /* NCCI allocate/remove function                                    */
776 /*------------------------------------------------------------------*/
777 
778 static dword ncci_mapping_bug = 0;
779 
780 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
781 {
782   DIVA_CAPI_ADAPTER   *a;
783   word ncci, i, j, k;
784 
785   a = plci->adapter;
786   if (!ch || a->ch_ncci[ch])
787   {
788     ncci_mapping_bug++;
789     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
790       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
791     ncci = ch;
792   }
793   else
794   {
795     if (force_ncci)
796       ncci = force_ncci;
797     else
798     {
799       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
800         ncci = ch;
801       else
802       {
803         ncci = 1;
804         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
805           ncci++;
806         if (ncci == MAX_NCCI+1)
807         {
808           ncci_mapping_bug++;
809           i = 1;
810           do
811           {
812             j = 1;
813             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
814               j++;
815             k = j;
816             if (j < MAX_NCCI+1)
817             {
818               do
819               {
820                 j++;
821               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
822             }
823           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
824           if (i < MAX_NL_CHANNEL+1)
825           {
826             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
827               ncci_mapping_bug, ch, force_ncci, i, k, j));
828           }
829           else
830           {
831             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
832               ncci_mapping_bug, ch, force_ncci));
833           }
834           ncci = ch;
835         }
836       }
837       a->ncci_plci[ncci] = plci->Id;
838       a->ncci_state[ncci] = IDLE;
839       if (!plci->ncci_ring_list)
840         plci->ncci_ring_list = ncci;
841       else
842         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
843       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
844     }
845     a->ncci_ch[ncci] = ch;
846     a->ch_ncci[ch] = (byte) ncci;
847     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
848       ncci_mapping_bug, ch, force_ncci, ch, ncci));
849   }
850   return (ncci);
851 }
852 
853 
854 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
855 {
856   DIVA_CAPI_ADAPTER   *a;
857   APPL   *appl;
858   word i, ncci_code;
859   dword Id;
860 
861   a = plci->adapter;
862   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
863   if (ncci)
864   {
865     if (a->ncci_plci[ncci] == plci->Id)
866     {
867       if (!plci->appl)
868       {
869         ncci_mapping_bug++;
870         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
871           ncci_mapping_bug, Id));
872       }
873       else
874       {
875         appl = plci->appl;
876         ncci_code = ncci | (((word) a->Id) << 8);
877         for (i = 0; i < appl->MaxBuffer; i++)
878         {
879           if ((appl->DataNCCI[i] == ncci_code)
880            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
881           {
882             appl->DataNCCI[i] = 0;
883           }
884         }
885       }
886     }
887   }
888   else
889   {
890     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
891     {
892       if (a->ncci_plci[ncci] == plci->Id)
893       {
894         if (!plci->appl)
895         {
896           ncci_mapping_bug++;
897           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
898             ncci_mapping_bug, Id));
899         }
900         else
901         {
902           appl = plci->appl;
903           ncci_code = ncci | (((word) a->Id) << 8);
904           for (i = 0; i < appl->MaxBuffer; i++)
905           {
906             if ((appl->DataNCCI[i] == ncci_code)
907              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
908             {
909               appl->DataNCCI[i] = 0;
910             }
911           }
912         }
913       }
914     }
915   }
916 }
917 
918 
919 static void cleanup_ncci_data (PLCI   *plci, word ncci)
920 {
921   NCCI   *ncci_ptr;
922 
923   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
924   {
925     ncci_ptr = &(plci->adapter->ncci[ncci]);
926     if (plci->appl)
927     {
928       while (ncci_ptr->data_pending != 0)
929       {
930         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
931           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
932         (ncci_ptr->data_out)++;
933         if (ncci_ptr->data_out == MAX_DATA_B3)
934           ncci_ptr->data_out = 0;
935         (ncci_ptr->data_pending)--;
936       }
937     }
938     ncci_ptr->data_out = 0;
939     ncci_ptr->data_pending = 0;
940     ncci_ptr->data_ack_out = 0;
941     ncci_ptr->data_ack_pending = 0;
942   }
943 }
944 
945 
946 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
947 {
948   DIVA_CAPI_ADAPTER   *a;
949   dword Id;
950   word i;
951 
952   a = plci->adapter;
953   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
954   if (!preserve_ncci)
955     ncci_free_receive_buffers (plci, ncci);
956   if (ncci)
957   {
958     if (a->ncci_plci[ncci] != plci->Id)
959     {
960       ncci_mapping_bug++;
961       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
962         ncci_mapping_bug, Id, preserve_ncci));
963     }
964     else
965     {
966       cleanup_ncci_data (plci, ncci);
967       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
968         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
969       a->ch_ncci[a->ncci_ch[ncci]] = 0;
970       if (!preserve_ncci)
971       {
972         a->ncci_ch[ncci] = 0;
973         a->ncci_plci[ncci] = 0;
974         a->ncci_state[ncci] = IDLE;
975         i = plci->ncci_ring_list;
976         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
977           i = a->ncci_next[i];
978         if ((i != 0) && (a->ncci_next[i] == ncci))
979         {
980           if (i == ncci)
981             plci->ncci_ring_list = 0;
982           else if (plci->ncci_ring_list == ncci)
983             plci->ncci_ring_list = i;
984           a->ncci_next[i] = a->ncci_next[ncci];
985         }
986         a->ncci_next[ncci] = 0;
987       }
988     }
989   }
990   else
991   {
992     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
993     {
994       if (a->ncci_plci[ncci] == plci->Id)
995       {
996         cleanup_ncci_data (plci, ncci);
997         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
998           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
999         a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000         if (!preserve_ncci)
1001         {
1002           a->ncci_ch[ncci] = 0;
1003           a->ncci_plci[ncci] = 0;
1004           a->ncci_state[ncci] = IDLE;
1005           a->ncci_next[ncci] = 0;
1006         }
1007       }
1008     }
1009     if (!preserve_ncci)
1010       plci->ncci_ring_list = 0;
1011   }
1012 }
1013 
1014 
1015 /*------------------------------------------------------------------*/
1016 /* PLCI remove function                                             */
1017 /*------------------------------------------------------------------*/
1018 
1019 static void plci_free_msg_in_queue (PLCI   *plci)
1020 {
1021   word i;
1022 
1023   if (plci->appl)
1024   {
1025     i = plci->msg_in_read_pos;
1026     while (i != plci->msg_in_write_pos)
1027     {
1028       if (i == plci->msg_in_wrap_pos)
1029         i = 0;
1030       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031       {
1032 
1033         TransmitBufferFree (plci->appl,
1034           (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1035 
1036       }
1037 
1038       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1039         MSG_IN_OVERHEAD + 3) & 0xfffc;
1040 
1041     }
1042   }
1043   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1046 }
1047 
1048 
1049 static void plci_remove(PLCI   * plci)
1050 {
1051 
1052   if(!plci) {
1053     dbug(1,dprintf("plci_remove(no plci)"));
1054     return;
1055   }
1056   init_internal_command_queue (plci);
1057   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058   if(plci_remove_check(plci))
1059   {
1060     return;
1061   }
1062   if (plci->Sig.Id == 0xff)
1063   {
1064     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065     if (plci->NL.Id && !plci->nl_remove_id)
1066     {
1067       nl_req_ncci(plci,REMOVE,0);
1068       send_req(plci);
1069     }
1070   }
1071   else
1072   {
1073     if (!plci->sig_remove_id
1074      && (plci->Sig.Id
1075       || (plci->req_in!=plci->req_out)
1076       || (plci->nl_req || plci->sig_req)))
1077     {
1078       sig_req(plci,HANGUP,0);
1079       send_req(plci);
1080     }
1081   }
1082   ncci_remove (plci, 0, false);
1083   plci_free_msg_in_queue (plci);
1084 
1085   plci->channels = 0;
1086   plci->appl = NULL;
1087   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088     plci->State = OUTG_DIS_PENDING;
1089 }
1090 
1091 /*------------------------------------------------------------------*/
1092 /* Application Group function helpers                               */
1093 /*------------------------------------------------------------------*/
1094 
1095 static void set_group_ind_mask (PLCI   *plci)
1096 {
1097   word i;
1098 
1099   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100     plci->group_optimization_mask_table[i] = 0xffffffffL;
1101 }
1102 
1103 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1104 {
1105   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106 }
1107 
1108 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1109 {
1110   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111 }
1112 
1113 /*------------------------------------------------------------------*/
1114 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1115 /*------------------------------------------------------------------*/
1116 
1117 static void clear_c_ind_mask (PLCI   *plci)
1118 {
1119   word i;
1120 
1121   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122     plci->c_ind_mask_table[i] = 0;
1123 }
1124 
1125 static byte c_ind_mask_empty (PLCI   *plci)
1126 {
1127   word i;
1128 
1129   i = 0;
1130   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1131     i++;
1132   return (i == C_IND_MASK_DWORDS);
1133 }
1134 
1135 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1136 {
1137   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138 }
1139 
1140 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1141 {
1142   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143 }
1144 
1145 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1146 {
1147   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148 }
1149 
1150 static void dump_c_ind_mask (PLCI   *plci)
1151 {
1152 static char hex_digit_table[0x10] =
1153   {'','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1154   word i, j, k;
1155   dword d;
1156     char *p;
1157     char buf[40];
1158 
1159   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1160   {
1161     p = buf + 36;
1162     *p = '\0';
1163     for (j = 0; j < 4; j++)
1164     {
1165       if (i+j < C_IND_MASK_DWORDS)
1166       {
1167         d = plci->c_ind_mask_table[i+j];
1168         for (k = 0; k < 8; k++)
1169         {
1170           *(--p) = hex_digit_table[d & 0xf];
1171           d >>= 4;
1172         }
1173       }
1174       else if (i != 0)
1175       {
1176         for (k = 0; k < 8; k++)
1177           *(--p) = ' ';
1178       }
1179       *(--p) = ' ';
1180     }
1181     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1182   }
1183 }
1184 
1185 
1186 
1187 
1188 
1189 #define dump_plcis(a)
1190 
1191 
1192 
1193 /*------------------------------------------------------------------*/
1194 /* translation function for each message                            */
1195 /*------------------------------------------------------------------*/
1196 
1197 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1198                         PLCI *plci, APPL *appl, API_PARSE *parms)
1199 {
1200   word ch;
1201   word i;
1202   word Info;
1203   word CIP;
1204   byte LinkLayer;
1205   API_PARSE * ai;
1206   API_PARSE * bp;
1207     API_PARSE ai_parms[5];
1208   word channel = 0;
1209   dword ch_mask;
1210   byte m;
1211   static byte esc_chi[35] = {0x02,0x18,0x01};
1212   static byte lli[2] = {0x01,0x00};
1213   byte noCh = 0;
1214   word dir = 0;
1215   byte   *p_chi = "";
1216 
1217   for(i=0;i<5;i++) ai_parms[i].length = 0;
1218 
1219   dbug(1,dprintf("connect_req(%d)",parms->length));
1220   Info = _WRONG_IDENTIFIER;
1221   if(a)
1222   {
1223     if(a->adapter_disabled)
1224     {
1225       dbug(1,dprintf("adapter disabled"));
1226       Id = ((word)1<<8)|a->Id;
1227       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1228       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1229       return false;
1230     }
1231     Info = _OUT_OF_PLCI;
1232     if((i=get_plci(a)))
1233     {
1234       Info = 0;
1235       plci = &a->plci[i-1];
1236       plci->appl = appl;
1237       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1238       /* check 'external controller' bit for codec support */
1239       if(Id & EXT_CONTROLLER)
1240       {
1241         if(AdvCodecSupport(a, plci, appl, 0) )
1242         {
1243           plci->Id = 0;
1244           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1245           return 2;
1246         }
1247       }
1248       ai = &parms[9];
1249       bp = &parms[5];
1250       ch = 0;
1251       if(bp->length)LinkLayer = bp->info[3];
1252       else LinkLayer = 0;
1253       if(ai->length)
1254       {
1255         ch=0xffff;
1256         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1257         {
1258           ch = 0;
1259           if(ai_parms[0].length)
1260           {
1261             ch = GET_WORD(ai_parms[0].info+1);
1262             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1263             if(ch==4) /* explizit CHI in message */
1264             {
1265               /* check length of B-CH struct */
1266               if((ai_parms[0].info)[3]>=1)
1267               {
1268                 if((ai_parms[0].info)[4]==CHI)
1269                 {
1270                   p_chi = &((ai_parms[0].info)[5]);
1271                 }
1272                 else
1273                 {
1274                   p_chi = &((ai_parms[0].info)[3]);
1275                 }
1276                 if(p_chi[0]>35) /* check length of channel ID */
1277                 {
1278                   Info = _WRONG_MESSAGE_FORMAT;    
1279                 }
1280               }
1281               else Info = _WRONG_MESSAGE_FORMAT;    
1282             }
1283 
1284             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1285             {
1286               dir = GET_WORD(ai_parms[0].info+3);
1287               ch_mask = 0;
1288               m = 0x3f;
1289               for(i=0; i+5<=ai_parms[0].length; i++)
1290               {
1291                 if(ai_parms[0].info[i+5]!=0)
1292                 {
1293                   if((ai_parms[0].info[i+5] | m) != 0xff)
1294                     Info = _WRONG_MESSAGE_FORMAT;
1295                   else
1296                   {
1297                     if (ch_mask == 0)
1298                       channel = i;
1299                     ch_mask |= 1L << i;
1300                   }
1301                 }
1302                 m = 0;
1303               }
1304               if (ch_mask == 0)
1305                 Info = _WRONG_MESSAGE_FORMAT;
1306               if (!Info)
1307               {
1308                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1309                 {
1310                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1311                   for(i=0; i+5<=ai_parms[0].length; i++)
1312                     esc_chi[i+3] = ai_parms[0].info[i+5];
1313                 }
1314                 else
1315                   esc_chi[0] = 2;
1316                 esc_chi[2] = (byte)channel;
1317                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1318                 add_p(plci,LLI,lli);
1319                 add_p(plci,ESC,esc_chi);
1320                 plci->State = LOCAL_CONNECT;
1321                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1322               }
1323             }
1324           }
1325         }
1326         else  Info = _WRONG_MESSAGE_FORMAT;
1327       }
1328 
1329       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1330       plci->command = _CONNECT_R;
1331       plci->number = Number;
1332       /* x.31 or D-ch free SAPI in LinkLayer? */
1333       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1334       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1335       {
1336         /* B-channel used for B3 connections (ch==0), or no B channel    */
1337         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1338         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1339         else     Info = add_b1(plci,&parms[5],ch,0); 
1340         add_s(plci,OAD,&parms[2]);
1341         add_s(plci,OSA,&parms[4]);
1342         add_s(plci,BC,&parms[6]);
1343         add_s(plci,LLC,&parms[7]);
1344         add_s(plci,HLC,&parms[8]);
1345         CIP = GET_WORD(parms[0].info);
1346         if (a->Info_Mask[appl->Id-1] & 0x200)
1347         {
1348           /* early B3 connect (CIP mask bit 9) no release after a disc */
1349           add_p(plci,LLI,"\x01\x01");
1350         }
1351         if(GET_WORD(parms[0].info)<29) {
1352           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1353           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1354         }
1355         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1356         sig_req(plci,ASSIGN,DSIG_ID);
1357       }
1358       else if(ch==1) {
1359 
1360         /* D-Channel used for B3 connections */
1361         plci->Sig.Id = 0xff;
1362         Info = 0;
1363       }
1364 
1365       if(!Info && ch!=2 && !noCh ) {
1366         Info = add_b23(plci,&parms[5]);
1367         if(!Info) {
1368           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1369         }
1370       }
1371 
1372       if(!Info)
1373       {
1374         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1375         {
1376           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1377           {
1378             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1379             plci->spoofed_msg = CALL_REQ;
1380             plci->internal_command = BLOCK_PLCI;
1381             plci->command = 0;
1382             dbug(1,dprintf("Spoof"));
1383             send_req(plci);
1384             return false;
1385           }
1386           if(ch==4)add_p(plci,CHI,p_chi);
1387           add_s(plci,CPN,&parms[1]);
1388           add_s(plci,DSA,&parms[3]);
1389           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1390           add_ai(plci,&parms[9]);
1391           if(!dir)sig_req(plci,CALL_REQ,0);
1392           else
1393           {
1394             plci->command = PERM_LIST_REQ;
1395             plci->appl = appl;
1396             sig_req(plci,LISTEN_REQ,0);
1397             send_req(plci);
1398             return false;
1399           }
1400         }
1401         send_req(plci);
1402         return false;
1403       }
1404       plci->Id = 0;
1405     }
1406   }
1407   sendf(appl,
1408         _CONNECT_R|CONFIRM,
1409         Id,
1410         Number,
1411         "w",Info);
1412   return 2;
1413 }
1414 
1415 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1416                         PLCI *plci, APPL *appl, API_PARSE *parms)
1417 {
1418   word i, Info;
1419   word Reject;
1420   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1421   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1422   API_PARSE * ai;
1423     API_PARSE ai_parms[5];
1424   word ch=0;
1425 
1426   if(!plci) {
1427     dbug(1,dprintf("connect_res(no plci)"));
1428     return 0;  /* no plci, no send */
1429   }
1430 
1431   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1432   for(i=0;i<5;i++) ai_parms[i].length = 0;
1433   ai = &parms[5];
1434   dbug(1,dprintf("ai->length=%d",ai->length));
1435 
1436   if(ai->length)
1437   {
1438     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1439     {
1440       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1441       ch = 0;
1442       if(ai_parms[0].length)
1443       {
1444         ch = GET_WORD(ai_parms[0].info+1);
1445         dbug(1,dprintf("BCH-I=0x%x",ch));
1446       }
1447     }
1448   }
1449 
1450   if(plci->State==INC_CON_CONNECTED_ALERT)
1451   {
1452     dbug(1,dprintf("Connected Alert Call_Res"));
1453     if (a->Info_Mask[appl->Id-1] & 0x200)
1454     {
1455     /* early B3 connect (CIP mask bit 9) no release after a disc */
1456       add_p(plci,LLI,"\x01\x01");
1457     }
1458     add_s(plci, CONN_NR, &parms[2]);
1459     add_s(plci, LLC, &parms[4]);
1460     add_ai(plci, &parms[5]);
1461     plci->State = INC_CON_ACCEPT;
1462     sig_req(plci, CALL_RES,0);
1463     return 1;
1464   }
1465   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1466     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1467     dump_c_ind_mask (plci);
1468     Reject = GET_WORD(parms[0].info);
1469     dbug(1,dprintf("Reject=0x%x",Reject));
1470     if(Reject) 
1471     {
1472       if(c_ind_mask_empty (plci)) 
1473       {
1474         if((Reject&0xff00)==0x3400) 
1475         {
1476           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1477           add_p(plci,ESC,esc_t);
1478           add_ai(plci, &parms[5]);
1479           sig_req(plci,REJECT,0);
1480         }      
1481         else if(Reject==1 || Reject>9) 
1482         {
1483           add_ai(plci, &parms[5]);
1484           sig_req(plci,HANGUP,0);
1485         }
1486         else 
1487         {
1488           esc_t[2] = cau_t[(Reject&0x000f)];
1489           add_p(plci,ESC,esc_t);
1490           add_ai(plci, &parms[5]);
1491           sig_req(plci,REJECT,0);
1492         }
1493         plci->appl = appl;
1494       }
1495       else 
1496       {
1497         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1498       }
1499     }
1500     else {
1501       plci->appl = appl;
1502       if(Id & EXT_CONTROLLER){
1503         if(AdvCodecSupport(a, plci, appl, 0)){
1504           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1505           sig_req(plci,HANGUP,0);
1506           return 1;
1507         }
1508         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1509         {
1510           Info = add_b23(plci, &parms[1]);
1511           if (Info)
1512           {
1513             dbug(1,dprintf("connect_res(error from add_b23)"));
1514             sig_req(plci,HANGUP,0);
1515             return 1;
1516           }
1517           if(plci->adv_nl)
1518           {
1519             nl_req_ncci(plci, ASSIGN, 0);
1520           }
1521         }
1522       }
1523       else
1524       {
1525         plci->tel = 0;
1526         if(ch!=2)
1527         {
1528           Info = add_b23(plci, &parms[1]);
1529           if (Info)
1530           {
1531             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1532             sig_req(plci,HANGUP,0);
1533             return 1;
1534           }
1535         }
1536         nl_req_ncci(plci, ASSIGN, 0);
1537       }
1538 
1539       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1540       {
1541         api_save_msg(parms, "wsssss", &plci->saved_msg);
1542         plci->spoofed_msg = CALL_RES;
1543         plci->internal_command = BLOCK_PLCI;
1544         plci->command = 0;
1545         dbug(1,dprintf("Spoof"));
1546       }
1547       else
1548       {
1549         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1550         if (a->Info_Mask[appl->Id-1] & 0x200)
1551         {
1552           /* early B3 connect (CIP mask bit 9) no release after a disc */
1553           add_p(plci,LLI,"\x01\x01");
1554         }
1555         add_s(plci, CONN_NR, &parms[2]);
1556         add_s(plci, LLC, &parms[4]);
1557         add_ai(plci, &parms[5]);
1558         plci->State = INC_CON_ACCEPT;
1559         sig_req(plci, CALL_RES,0);
1560       }
1561 
1562       for(i=0; i<max_appl; i++) {
1563         if(test_c_ind_mask_bit (plci, i)) {
1564           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1565         }
1566       }
1567     }
1568   }
1569   return 1;
1570 }
1571 
1572 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1573                           PLCI *plci, APPL *appl, API_PARSE *msg)
1574 {
1575   dbug(1,dprintf("connect_a_res"));
1576   return false;
1577 }
1578 
1579 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1580                            PLCI *plci, APPL *appl, API_PARSE *msg)
1581 {
1582   word Info;
1583   word i;
1584 
1585   dbug(1,dprintf("disconnect_req"));
1586 
1587   Info = _WRONG_IDENTIFIER;
1588 
1589   if(plci)
1590   {
1591     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1592     {
1593       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1594       plci->appl = appl;
1595       for(i=0; i<max_appl; i++)
1596       {
1597         if(test_c_ind_mask_bit (plci, i))
1598           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1599       }
1600       plci->State = OUTG_DIS_PENDING;
1601     }
1602     if(plci->Sig.Id && plci->appl)
1603     {
1604       Info = 0;
1605         if(plci->Sig.Id!=0xff)
1606         {
1607           if(plci->State!=INC_DIS_PENDING)
1608           {
1609             add_ai(plci, &msg[0]);
1610             sig_req(plci,HANGUP,0);
1611             plci->State = OUTG_DIS_PENDING;
1612             return 1;
1613           }
1614         }
1615         else
1616         {
1617           if (plci->NL.Id && !plci->nl_remove_id)
1618           {
1619             mixer_remove (plci);
1620             nl_req_ncci(plci,REMOVE,0);
1621           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1622           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1623           plci->State = INC_DIS_PENDING;
1624           }
1625           return 1;
1626         }
1627       }
1628     }
1629 
1630   if(!appl)  return false;
1631   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1632   return false;
1633 }
1634 
1635 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1636                            PLCI *plci, APPL *appl, API_PARSE *msg)
1637 {
1638   dbug(1,dprintf("disconnect_res"));
1639   if(plci)
1640   {
1641         /* clear ind mask bit, just in case of collsion of          */
1642         /* DISCONNECT_IND and CONNECT_RES                           */
1643     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1644     ncci_free_receive_buffers (plci, 0);
1645     if(plci_remove_check(plci))
1646     {
1647       return 0;
1648     }
1649     if(plci->State==INC_DIS_PENDING
1650     || plci->State==SUSPENDING) {
1651       if(c_ind_mask_empty (plci)) {
1652         if(plci->State!=SUSPENDING)plci->State = IDLE;
1653         dbug(1,dprintf("chs=%d",plci->channels));
1654         if(!plci->channels) {
1655           plci_remove(plci);
1656         }
1657       }
1658     }
1659   }
1660   return 0;
1661 }
1662 
1663 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1664                        PLCI *plci, APPL *appl, API_PARSE *parms)
1665 {
1666   word Info;
1667   byte i;
1668 
1669   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1670 
1671   Info = _WRONG_IDENTIFIER;
1672   if(a) {
1673     Info = 0;
1674     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1675     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1676     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1677     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1678       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1679     }
1680 
1681     /* check if external controller listen and switch listen on or off*/
1682     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1683       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1684         dummy_plci.State = IDLE;
1685         a->codec_listen[appl->Id-1] = &dummy_plci;
1686         a->TelOAD[0] = (byte)(parms[3].length);
1687         for(i=1;parms[3].length>=i && i<22;i++) {
1688           a->TelOAD[i] = parms[3].info[i];
1689         }
1690         a->TelOAD[i] = 0;
1691         a->TelOSA[0] = (byte)(parms[4].length);
1692         for(i=1;parms[4].length>=i && i<22;i++) {
1693           a->TelOSA[i] = parms[4].info[i];
1694         }
1695         a->TelOSA[i] = 0;
1696       }
1697       else Info = 0x2002; /* wrong controller, codec not supported */
1698     }
1699     else{               /* clear listen */
1700       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1701     }
1702   }
1703   sendf(appl,
1704         _LISTEN_R|CONFIRM,
1705         Id,
1706         Number,
1707         "w",Info);
1708 
1709   if (a) listen_check(a);
1710   return false;
1711 }
1712 
1713 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1714                      PLCI *plci, APPL *appl, API_PARSE *msg)
1715 {
1716   word i;
1717   API_PARSE * ai;
1718   PLCI   * rc_plci = NULL;
1719     API_PARSE ai_parms[5];
1720   word Info = 0;
1721 
1722   dbug(1,dprintf("info_req"));
1723   for(i=0;i<5;i++) ai_parms[i].length = 0;
1724 
1725   ai = &msg[1];
1726 
1727   if(ai->length)
1728   {
1729     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1730     {
1731       dbug(1,dprintf("AddInfo wrong"));
1732       Info = _WRONG_MESSAGE_FORMAT;
1733     }
1734   }
1735   if(!a) Info = _WRONG_STATE;
1736 
1737   if(!Info && plci)
1738   {                /* no fac, with CPN, or KEY */
1739     rc_plci = plci;
1740     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1741     {
1742       /* overlap sending option */
1743       dbug(1,dprintf("OvlSnd"));
1744       add_s(plci,CPN,&msg[0]);
1745       add_s(plci,KEY,&ai_parms[1]);
1746       sig_req(plci,INFO_REQ,0);
1747       send_req(plci);
1748       return false;
1749     }
1750 
1751     if(plci->State && ai_parms[2].length)
1752     {
1753       /* User_Info option */
1754       dbug(1,dprintf("UUI"));
1755       add_s(plci,UUI,&ai_parms[2]);
1756       sig_req(plci,USER_DATA,0);
1757     }
1758     else if(plci->State && ai_parms[3].length)
1759     {
1760       /* Facility option */
1761       dbug(1,dprintf("FAC"));
1762       add_s(plci,CPN,&msg[0]);
1763       add_ai(plci, &msg[1]);
1764       sig_req(plci,FACILITY_REQ,0);
1765     }
1766     else
1767     {
1768       Info = _WRONG_STATE;
1769     }
1770   }
1771   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1772   {
1773     /* NCR_Facility option -> send UUI and Keypad too */
1774     dbug(1,dprintf("NCR_FAC"));
1775     if((i=get_plci(a)))
1776     {
1777       rc_plci = &a->plci[i-1];
1778       appl->NullCREnable  = true;
1779       rc_plci->internal_command = C_NCR_FAC_REQ;
1780       rc_plci->appl = appl;
1781       add_p(rc_plci,CAI,"\x01\x80");
1782       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1783       sig_req(rc_plci,ASSIGN,DSIG_ID);
1784       send_req(rc_plci);
1785     }
1786     else
1787     {
1788       Info = _OUT_OF_PLCI;
1789     }
1790 
1791     if(!Info)
1792     {
1793       add_s(rc_plci,CPN,&msg[0]);
1794       add_ai(rc_plci, &msg[1]);
1795       sig_req(rc_plci,NCR_FACILITY,0);
1796       send_req(rc_plci);
1797       return false;
1798      /* for application controlled supplementary services    */
1799     }
1800   }
1801 
1802   if (!rc_plci)
1803   {
1804     Info = _WRONG_MESSAGE_FORMAT;
1805   }
1806 
1807   if(!Info)
1808   {
1809     send_req(rc_plci);
1810   }
1811   else
1812   {  /* appl is not assigned to a PLCI or error condition */
1813     dbug(1,dprintf("localInfoCon"));
1814     sendf(appl,
1815           _INFO_R|CONFIRM,
1816           Id,
1817           Number,
1818           "w",Info);
1819   }
1820   return false;
1821 }
1822 
1823 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1824                      PLCI *plci, APPL *appl, API_PARSE *msg)
1825 {
1826   dbug(1,dprintf("info_res"));
1827   return false;
1828 }
1829 
1830 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1831                       PLCI *plci, APPL *appl, API_PARSE *msg)
1832 {
1833   word Info;
1834   byte ret;
1835 
1836   dbug(1,dprintf("alert_req"));
1837 
1838   Info = _WRONG_IDENTIFIER;
1839   ret = false;
1840   if(plci) {
1841     Info = _ALERT_IGNORED;
1842     if(plci->State!=INC_CON_ALERT) {
1843       Info = _WRONG_STATE;
1844       if(plci->State==INC_CON_PENDING) {
1845         Info = 0;
1846         plci->State=INC_CON_ALERT;
1847         add_ai(plci, &msg[0]);
1848         sig_req(plci,CALL_ALERT,0);
1849         ret = 1;
1850       }
1851     }
1852   }
1853   sendf(appl,
1854         _ALERT_R|CONFIRM,
1855         Id,
1856         Number,
1857         "w",Info);
1858   return ret;
1859 }
1860 
1861 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1862                          PLCI *plci, APPL *appl, API_PARSE *msg)
1863 {
1864   word Info = 0;
1865   word i    = 0;
1866 
1867   word selector;
1868   word SSreq;
1869   long relatedPLCIvalue;
1870   DIVA_CAPI_ADAPTER   * relatedadapter;
1871   byte * SSparms  = "";
1872     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1873     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1874   API_PARSE * parms;
1875     API_PARSE ss_parms[11];
1876   PLCI   *rplci;
1877     byte cai[15];
1878   dword d;
1879     API_PARSE dummy;
1880 
1881   dbug(1,dprintf("facility_req"));
1882   for(i=0;i<9;i++) ss_parms[i].length = 0;
1883 
1884   parms = &msg[1];
1885 
1886   if(!a)
1887   {
1888     dbug(1,dprintf("wrong Ctrl"));
1889     Info = _WRONG_IDENTIFIER;
1890   }
1891 
1892   selector = GET_WORD(msg[0].info);
1893 
1894   if(!Info)
1895   {
1896     switch(selector)
1897     {
1898       case SELECTOR_HANDSET:
1899         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1900         break;
1901 
1902       case SELECTOR_SU_SERV:
1903         if(!msg[1].length)
1904         {
1905           Info = _WRONG_MESSAGE_FORMAT;
1906           break;
1907         }
1908         SSreq = GET_WORD(&(msg[1].info[1]));
1909         PUT_WORD(&RCparms[1],SSreq);
1910         SSparms = RCparms;
1911         switch(SSreq)
1912         {
1913           case S_GET_SUPPORTED_SERVICES:
1914             if((i=get_plci(a)))
1915             {
1916               rplci = &a->plci[i-1];
1917               rplci->appl = appl;
1918               add_p(rplci,CAI,"\x01\x80");
1919               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1920               sig_req(rplci,ASSIGN,DSIG_ID);
1921               send_req(rplci);
1922             }
1923             else
1924             {
1925               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1926               SSparms = (byte *)SSstruct;
1927               break;
1928             }
1929             rplci->internal_command = GETSERV_REQ_PEND;
1930             rplci->number = Number;
1931             rplci->appl = appl;
1932             sig_req(rplci,S_SUPPORTED,0);
1933             send_req(rplci);
1934             return false;
1935             break;
1936 
1937           case S_LISTEN:
1938             if(parms->length==7)
1939             {
1940               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1941               {
1942                 dbug(1,dprintf("format wrong"));
1943                 Info = _WRONG_MESSAGE_FORMAT;
1944                 break;
1945               }
1946             }
1947             else
1948             {
1949               Info = _WRONG_MESSAGE_FORMAT;
1950               break;
1951             }
1952             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1953             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1954             {
1955               if((i=get_plci(a)))
1956               {
1957                 rplci = &a->plci[i-1];
1958                 rplci->appl = appl;
1959                 add_p(rplci,CAI,"\x01\x80");
1960                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1961                 sig_req(rplci,ASSIGN,DSIG_ID);
1962                 send_req(rplci);
1963               }
1964               else
1965               {
1966                 break;
1967               }
1968               rplci->internal_command = GET_MWI_STATE;
1969               rplci->number = Number;
1970               sig_req(rplci,MWI_POLL,0);
1971               send_req(rplci);
1972             }
1973             break;
1974 
1975           case S_HOLD:
1976             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1977             if(plci && plci->State && plci->SuppState==IDLE)
1978             {
1979               plci->SuppState = HOLD_REQUEST;
1980               plci->command = C_HOLD_REQ;
1981               add_s(plci,CAI,&ss_parms[1]);
1982               sig_req(plci,CALL_HOLD,0);
1983               send_req(plci);
1984               return false;
1985             }
1986             else Info = 0x3010;                    /* wrong state           */
1987             break;
1988           case S_RETRIEVE:
1989             if(plci && plci->State && plci->SuppState==CALL_HELD)
1990             {
1991               if(Id & EXT_CONTROLLER)
1992               {
1993                 if(AdvCodecSupport(a, plci, appl, 0))
1994                 {
1995                   Info = 0x3010;                    /* wrong state           */
1996                   break;
1997                 }
1998               }
1999               else plci->tel = 0;
2000 
2001               plci->SuppState = RETRIEVE_REQUEST;
2002               plci->command = C_RETRIEVE_REQ;
2003               if(plci->spoofed_msg==SPOOFING_REQUIRED)
2004               {
2005                 plci->spoofed_msg = CALL_RETRIEVE;
2006                 plci->internal_command = BLOCK_PLCI;
2007                 plci->command = 0;
2008                 dbug(1,dprintf("Spoof"));
2009                 return false;
2010               }
2011               else
2012               {
2013                 sig_req(plci,CALL_RETRIEVE,0);
2014                 send_req(plci);
2015                 return false;
2016               }
2017             }
2018             else Info = 0x3010;                    /* wrong state           */
2019             break;
2020           case S_SUSPEND:
2021             if(parms->length)
2022             {
2023               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2024               {
2025                 dbug(1,dprintf("format wrong"));
2026                 Info = _WRONG_MESSAGE_FORMAT;
2027                 break;
2028               }
2029             }
2030             if(plci && plci->State)
2031             {
2032               add_s(plci,CAI,&ss_parms[2]);
2033               plci->command = SUSPEND_REQ;
2034               sig_req(plci,SUSPEND,0);
2035               plci->State = SUSPENDING;
2036               send_req(plci);
2037             }
2038             else Info = 0x3010;                    /* wrong state           */
2039             break;
2040 
2041           case S_RESUME:
2042             if(!(i=get_plci(a)) )
2043             {
2044               Info = _OUT_OF_PLCI;
2045               break;
2046             }
2047             rplci = &a->plci[i-1];
2048             rplci->appl = appl;
2049             rplci->number = Number;
2050             rplci->tel = 0;
2051             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2052             /* check 'external controller' bit for codec support */
2053             if(Id & EXT_CONTROLLER)
2054             {
2055               if(AdvCodecSupport(a, rplci, appl, 0) )
2056               {
2057                 rplci->Id = 0;
2058                 Info = 0x300A;
2059                 break;
2060               }
2061             }
2062             if(parms->length)
2063             {
2064               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2065               {
2066                 dbug(1,dprintf("format wrong"));
2067                 rplci->Id = 0;
2068                 Info = _WRONG_MESSAGE_FORMAT;
2069                 break;
2070               }
2071             }
2072             dummy.length = 0;
2073             dummy.info = "\x00";
2074             add_b1(rplci, &dummy, 0, 0);
2075             if (a->Info_Mask[appl->Id-1] & 0x200)
2076             {
2077               /* early B3 connect (CIP mask bit 9) no release after a disc */
2078               add_p(rplci,LLI,"\x01\x01");
2079             }
2080             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2081             sig_req(rplci,ASSIGN,DSIG_ID);
2082             send_req(rplci);
2083             add_s(rplci,CAI,&ss_parms[2]);
2084             rplci->command = RESUME_REQ;
2085             sig_req(rplci,RESUME,0);
2086             rplci->State = RESUMING;
2087             send_req(rplci);
2088             break;
2089 
2090           case S_CONF_BEGIN: /* Request */
2091           case S_CONF_DROP:
2092           case S_CONF_ISOLATE:
2093           case S_CONF_REATTACH:
2094             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2095             {
2096               dbug(1,dprintf("format wrong"));
2097               Info = _WRONG_MESSAGE_FORMAT;
2098               break;
2099             }
2100             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2101             {
2102               d = GET_DWORD(ss_parms[2].info);     
2103               if(d>=0x80)
2104               {
2105                 dbug(1,dprintf("format wrong"));
2106                 Info = _WRONG_MESSAGE_FORMAT;
2107                 break;
2108               }
2109               plci->ptyState = (byte)SSreq;
2110               plci->command = 0;
2111               cai[0] = 2;
2112               switch(SSreq)
2113               {
2114               case S_CONF_BEGIN:
2115                   cai[1] = CONF_BEGIN;
2116                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2117                   break;
2118               case S_CONF_DROP:
2119                   cai[1] = CONF_DROP;
2120                   plci->internal_command = CONF_DROP_REQ_PEND;
2121                   break;
2122               case S_CONF_ISOLATE:
2123                   cai[1] = CONF_ISOLATE;
2124                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2125                   break;
2126               case S_CONF_REATTACH:
2127                   cai[1] = CONF_REATTACH;
2128                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2129                   break;
2130               }
2131               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2132               add_p(plci,CAI,cai);
2133               sig_req(plci,S_SERVICE,0);
2134               send_req(plci);
2135               return false;
2136             }
2137             else Info = 0x3010;                    /* wrong state           */
2138             break;
2139 
2140           case S_ECT:
2141           case S_3PTY_BEGIN:
2142           case S_3PTY_END:
2143           case S_CONF_ADD:
2144             if(parms->length==7)
2145             {
2146               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2147               {
2148                 dbug(1,dprintf("format wrong"));
2149                 Info = _WRONG_MESSAGE_FORMAT;
2150                 break;
2151               }
2152             }
2153             else if(parms->length==8) /* workaround for the T-View-S */
2154             {
2155               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2156               {
2157                 dbug(1,dprintf("format wrong"));
2158                 Info = _WRONG_MESSAGE_FORMAT;
2159                 break;
2160               }
2161             }
2162             else
2163             {
2164               Info = _WRONG_MESSAGE_FORMAT;
2165               break;
2166             }
2167             if(!msg[1].length)
2168             {
2169               Info = _WRONG_MESSAGE_FORMAT;
2170               break;
2171             }
2172             if (!plci)
2173             {
2174               Info = _WRONG_IDENTIFIER;
2175               break;
2176             }
2177             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2178             relatedPLCIvalue &= 0x0000FFFF;
2179             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2180             /* controller starts with 0 up to (max_adapter - 1) */
2181             if (((relatedPLCIvalue & 0x7f) == 0)
2182              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2183              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2184             {
2185               if(SSreq==S_3PTY_END)
2186               {
2187                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2188                 rplci = plci;
2189               }
2190               else
2191               {
2192                 Info = 0x3010;                    /* wrong state           */
2193                 break;
2194               }
2195             }
2196             else
2197             {  
2198               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2199               relatedPLCIvalue >>=8;
2200               /* find PLCI PTR*/
2201               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2202               {
2203                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2204                 {
2205                   rplci = &relatedadapter->plci[i];
2206                 }
2207               }
2208               if(!rplci || !relatedPLCIvalue)
2209               {
2210                 if(SSreq==S_3PTY_END)
2211                 {
2212                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2213                   rplci = plci;
2214                 }
2215                 else
2216                 {
2217                   Info = 0x3010;                    /* wrong state           */
2218                   break;
2219                 }
2220               }
2221             }
2222 /*
2223             dbug(1,dprintf("rplci:%x",rplci));
2224             dbug(1,dprintf("plci:%x",plci));
2225             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2226             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2227             dbug(1,dprintf("SSreq:%x",SSreq));
2228             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2229             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2230             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2231 */
2232             /* send PTY/ECT req, cannot check all states because of US stuff */
2233             if( !rplci->internal_command && rplci->appl )
2234             {
2235               plci->command = 0;
2236               rplci->relatedPTYPLCI = plci;
2237               plci->relatedPTYPLCI = rplci;
2238               rplci->ptyState = (byte)SSreq;
2239               if(SSreq==S_ECT)
2240               {
2241                 rplci->internal_command = ECT_REQ_PEND;
2242                 cai[1] = ECT_EXECUTE;
2243 
2244                 rplci->vswitchstate=0;
2245                 rplci->vsprot=0;
2246                 rplci->vsprotdialect=0;
2247                 plci->vswitchstate=0;
2248                 plci->vsprot=0;
2249                 plci->vsprotdialect=0;
2250 
2251               }
2252               else if(SSreq==S_CONF_ADD)
2253               {
2254                 rplci->internal_command = CONF_ADD_REQ_PEND;
2255                 cai[1] = CONF_ADD;
2256               }
2257               else
2258               {
2259                 rplci->internal_command = PTY_REQ_PEND;
2260                 cai[1] = (byte)(SSreq-3);
2261               }
2262               rplci->number = Number;
2263               if(plci!=rplci) /* explicit invocation */
2264               {
2265                 cai[0] = 2;
2266                 cai[2] = plci->Sig.Id;
2267                 dbug(1,dprintf("explicit invocation"));
2268               }
2269               else
2270               {
2271                 dbug(1,dprintf("implicit invocation"));
2272                 cai[0] = 1;
2273               }
2274               add_p(rplci,CAI,cai);
2275               sig_req(rplci,S_SERVICE,0);
2276               send_req(rplci);
2277               return false;
2278             }
2279             else
2280             {
2281               dbug(0,dprintf("Wrong line"));
2282               Info = 0x3010;                    /* wrong state           */
2283               break;
2284             }
2285             break;
2286 
2287           case S_CALL_DEFLECTION:
2288             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2289             {
2290               dbug(1,dprintf("format wrong"));
2291               Info = _WRONG_MESSAGE_FORMAT;
2292               break;
2293             }
2294             if (!plci)
2295             {
2296               Info = _WRONG_IDENTIFIER;
2297               break;
2298             }
2299             /* reuse unused screening indicator */
2300             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2301             plci->command = 0;
2302             plci->internal_command = CD_REQ_PEND;
2303             appl->CDEnable = true;
2304             cai[0] = 1;
2305             cai[1] = CALL_DEFLECTION;
2306             add_p(plci,CAI,cai);
2307             add_p(plci,CPN,ss_parms[3].info);
2308             sig_req(plci,S_SERVICE,0);
2309             send_req(plci);
2310             return false;
2311             break;
2312 
2313           case S_CALL_FORWARDING_START:
2314             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2315             {
2316               dbug(1,dprintf("format wrong"));
2317               Info = _WRONG_MESSAGE_FORMAT;
2318               break;
2319             }
2320 
2321             if((i=get_plci(a)))
2322             {
2323               rplci = &a->plci[i-1];
2324               rplci->appl = appl;
2325               add_p(rplci,CAI,"\x01\x80");
2326               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2327               sig_req(rplci,ASSIGN,DSIG_ID);
2328               send_req(rplci);
2329             }
2330             else
2331             {
2332               Info = _OUT_OF_PLCI;
2333               break;
2334             }
2335 
2336             /* reuse unused screening indicator */
2337             rplci->internal_command = CF_START_PEND;
2338             rplci->appl = appl;
2339             rplci->number = Number;
2340             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2341             cai[0] = 2;
2342             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2343             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2344             add_p(rplci,CAI,cai);
2345             add_p(rplci,OAD,ss_parms[5].info);
2346             add_p(rplci,CPN,ss_parms[6].info);
2347             sig_req(rplci,S_SERVICE,0);
2348             send_req(rplci);
2349             return false;
2350             break;
2351 
2352           case S_INTERROGATE_DIVERSION:
2353           case S_INTERROGATE_NUMBERS:
2354           case S_CALL_FORWARDING_STOP:
2355           case S_CCBS_REQUEST:
2356           case S_CCBS_DEACTIVATE:
2357           case S_CCBS_INTERROGATE:
2358             switch(SSreq)
2359             {
2360             case S_INTERROGATE_NUMBERS:
2361                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2362                 {
2363                   dbug(0,dprintf("format wrong"));
2364                   Info = _WRONG_MESSAGE_FORMAT;
2365                 }
2366                 break;
2367             case S_CCBS_REQUEST:
2368             case S_CCBS_DEACTIVATE:
2369                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2370                 {
2371                   dbug(0,dprintf("format wrong"));
2372                   Info = _WRONG_MESSAGE_FORMAT;
2373                 }
2374                 break;
2375             case S_CCBS_INTERROGATE:
2376                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2377                 {
2378                   dbug(0,dprintf("format wrong"));
2379                   Info = _WRONG_MESSAGE_FORMAT;
2380                 }
2381                 break;
2382             default:
2383             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2384             {
2385               dbug(0,dprintf("format wrong"));
2386               Info = _WRONG_MESSAGE_FORMAT;
2387               break;
2388             }
2389                 break;
2390             }
2391 
2392             if(Info) break;
2393             if((i=get_plci(a)))
2394             {
2395               rplci = &a->plci[i-1];
2396               switch(SSreq)
2397               {
2398                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2399                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2401                   break;
2402                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2403                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2404                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2405                   break;
2406                 case S_CALL_FORWARDING_STOP:
2407                   rplci->internal_command = CF_STOP_PEND;
2408                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2409                   break;
2410                 case S_CCBS_REQUEST:
2411                   cai[1] = CCBS_REQUEST;
2412                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2413                   break;
2414                 case S_CCBS_DEACTIVATE:
2415                   cai[1] = CCBS_DEACTIVATE;
2416                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2417                   break;
2418                 case S_CCBS_INTERROGATE:
2419                   cai[1] = CCBS_INTERROGATE;
2420                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2421                   break;
2422                 default:
2423                   cai[1] = 0;
2424                 break;
2425               }
2426               rplci->appl = appl;
2427               rplci->number = Number;
2428               add_p(rplci,CAI,"\x01\x80");
2429               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2430               sig_req(rplci,ASSIGN,DSIG_ID);
2431               send_req(rplci);
2432             }
2433             else
2434             {
2435               Info = _OUT_OF_PLCI;
2436               break;
2437             }
2438 
2439             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2440             switch(SSreq)
2441             {
2442             case S_INTERROGATE_NUMBERS:
2443                 cai[0] = 1;
2444                 add_p(rplci,CAI,cai);
2445                 break;
2446             case S_CCBS_REQUEST:
2447             case S_CCBS_DEACTIVATE:
2448                 cai[0] = 3;
2449                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2450                 add_p(rplci,CAI,cai);
2451                 break;
2452             case S_CCBS_INTERROGATE:
2453                 cai[0] = 3;
2454                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2455                 add_p(rplci,CAI,cai);
2456                 add_p(rplci,OAD,ss_parms[4].info);
2457                 break;
2458             default:
2459             cai[0] = 2;
2460             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2461             add_p(rplci,CAI,cai);
2462             add_p(rplci,OAD,ss_parms[5].info);
2463                 break;
2464             }
2465                         
2466             sig_req(rplci,S_SERVICE,0);
2467             send_req(rplci);
2468             return false;
2469             break;
2470 
2471           case S_MWI_ACTIVATE:
2472             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2473             {
2474               dbug(1,dprintf("format wrong"));
2475               Info = _WRONG_MESSAGE_FORMAT;
2476               break;
2477             }
2478             if(!plci)
2479             {                               
2480               if((i=get_plci(a)))
2481               {
2482                 rplci = &a->plci[i-1];
2483                 rplci->appl = appl;
2484                 rplci->cr_enquiry=true;
2485                 add_p(rplci,CAI,"\x01\x80");
2486                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2487                 sig_req(rplci,ASSIGN,DSIG_ID);
2488                 send_req(rplci);
2489               }
2490               else
2491               {
2492                 Info = _OUT_OF_PLCI;
2493                 break;
2494               }
2495             }
2496             else
2497             {
2498               rplci = plci;
2499               rplci->cr_enquiry=false;
2500             }
2501 
2502             rplci->command = 0;
2503             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2504             rplci->appl = appl;
2505             rplci->number = Number;
2506 
2507             cai[0] = 13;
2508             cai[1] = ACTIVATION_MWI; /* Function */
2509             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2510             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2511             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2512             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2513             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2514             add_p(rplci,CAI,cai);
2515             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2516             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2517             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2518             add_p(rplci,UID,ss_parms[10].info); /* Time */
2519             sig_req(rplci,S_SERVICE,0);
2520             send_req(rplci);
2521             return false;
2522 
2523           case S_MWI_DEACTIVATE:
2524             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2525             {
2526               dbug(1,dprintf("format wrong"));
2527               Info = _WRONG_MESSAGE_FORMAT;
2528               break;
2529             }
2530             if(!plci)
2531             {                               
2532               if((i=get_plci(a)))
2533               {
2534                 rplci = &a->plci[i-1];
2535                 rplci->appl = appl;
2536                 rplci->cr_enquiry=true;
2537                 add_p(rplci,CAI,"\x01\x80");
2538                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2539                 sig_req(rplci,ASSIGN,DSIG_ID);
2540                 send_req(rplci);
2541               }
2542               else
2543               {
2544                 Info = _OUT_OF_PLCI;
2545                 break;
2546               }
2547             }
2548             else
2549             {
2550               rplci = plci;
2551               rplci->cr_enquiry=false;
2552             }
2553 
2554             rplci->command = 0;
2555             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2556             rplci->appl = appl;
2557             rplci->number = Number;
2558 
2559             cai[0] = 5;
2560             cai[1] = DEACTIVATION_MWI; /* Function */
2561             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2562             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2563             add_p(rplci,CAI,cai);
2564             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2565             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2566             sig_req(rplci,S_SERVICE,0);
2567             send_req(rplci);
2568             return false;
2569 
2570           default:
2571             Info = 0x300E;  /* not supported */
2572             break;
2573         }
2574         break; /* case SELECTOR_SU_SERV: end */
2575 
2576 
2577       case SELECTOR_DTMF:
2578         return (dtmf_request (Id, Number, a, plci, appl, msg));
2579 
2580 
2581 
2582       case SELECTOR_LINE_INTERCONNECT:
2583         return (mixer_request (Id, Number, a, plci, appl, msg));
2584 
2585 
2586 
2587       case PRIV_SELECTOR_ECHO_CANCELLER:
2588         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2589         return (ec_request (Id, Number, a, plci, appl, msg));
2590 
2591       case SELECTOR_ECHO_CANCELLER:
2592         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2593         return (ec_request (Id, Number, a, plci, appl, msg));
2594 
2595 
2596       case SELECTOR_V42BIS:
2597       default:
2598         Info = _FACILITY_NOT_SUPPORTED;
2599         break;
2600     } /* end of switch(selector) */
2601   }
2602 
2603   dbug(1,dprintf("SendFacRc"));
2604   sendf(appl,
2605         _FACILITY_R|CONFIRM,
2606         Id,
2607         Number,
2608         "wws",Info,selector,SSparms);
2609   return false;
2610 }
2611 
2612 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2613                          PLCI *plci, APPL *appl, API_PARSE *msg)
2614 {
2615   dbug(1,dprintf("facility_res"));
2616   return false;
2617 }
2618 
2619 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2620                            PLCI *plci, APPL *appl, API_PARSE *parms)
2621 {
2622   word Info = 0;
2623   byte req;
2624   byte len;
2625   word w;
2626   word fax_control_bits, fax_feature_bits, fax_info_change;
2627   API_PARSE * ncpi;
2628     byte pvc[2];
2629 
2630     API_PARSE fax_parms[9];
2631   word i;
2632 
2633 
2634   dbug(1,dprintf("connect_b3_req"));
2635   if(plci)
2636   {
2637     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2638      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2639     {
2640       Info = _WRONG_STATE;
2641     }
2642     else
2643     {
2644       /* local reply if assign unsuccessfull
2645          or B3 protocol allows only one layer 3 connection
2646            and already connected
2647              or B2 protocol not any LAPD
2648                and connect_b3_req contradicts originate/answer direction */
2649       if (!plci->NL.Id
2650        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2651         && ((plci->channels != 0)
2652          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2653           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2654       {
2655         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2656                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2657         Info = _WRONG_STATE;
2658         sendf(appl,                                                        
2659               _CONNECT_B3_R|CONFIRM,
2660               Id,
2661               Number,
2662               "w",Info);
2663         return false;
2664       }
2665       plci->requested_options_conn = 0;
2666 
2667       req = N_CONNECT;
2668       ncpi = &parms[0];
2669       if(plci->B3_prot==2 || plci->B3_prot==3)
2670       {
2671         if(ncpi->length>2)
2672         {
2673           /* check for PVC */
2674           if(ncpi->info[2] || ncpi->info[3])
2675           {
2676             pvc[0] = ncpi->info[3];
2677             pvc[1] = ncpi->info[2];
2678             add_d(plci,2,pvc);
2679             req = N_RESET;
2680           }
2681           else
2682           {
2683             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2684             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2685           }
2686         }
2687       }
2688       else if(plci->B3_prot==5)
2689       {
2690         if (plci->NL.Id && !plci->nl_remove_id)
2691         {
2692           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2693           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2694           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2695            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2696           {
2697             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2698             fax_info_change = false;
2699             if (ncpi->length >= 4)
2700             {
2701               w = GET_WORD(&ncpi->info[3]);
2702               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2703               {
2704                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2705                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2706                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2707                 fax_info_change = true;
2708               }
2709               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2710               if (w & 0x0002)  /* Fax-polling request */
2711                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2712               if ((w & 0x0004) /* Request to send / poll another document */
2713                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2714               {
2715                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2716               }
2717               if (ncpi->length >= 6)
2718               {
2719                 w = GET_WORD(&ncpi->info[5]);
2720                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2721                 {
2722                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2723                   fax_info_change = true;
2724                 }
2725 
2726                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2727                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2728                 {
2729                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2730                 }
2731                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2732                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2733                 {
2734                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2735                 }
2736                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2737                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2738                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2739                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2740                 {
2741                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2742                     Info = _WRONG_MESSAGE_FORMAT;
2743                   else
2744                   {
2745                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2746                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2747       {
2748                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2749                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2750                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2751       }
2752                     w = fax_parms[4].length;
2753                     if (w > 20)
2754                       w = 20;
2755                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2756                     for (i = 0; i < w; i++)
2757                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2758                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2759                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2760                     w = fax_parms[5].length;
2761                     if (w > 20)
2762                       w = 20;
2763                     plci->fax_connect_info_buffer[len++] = (byte) w;
2764                     for (i = 0; i < w; i++)
2765                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2766                     w = fax_parms[6].length;
2767                     if (w > 20)
2768                       w = 20;
2769                     plci->fax_connect_info_buffer[len++] = (byte) w;
2770                     for (i = 0; i < w; i++)
2771                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2772                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2773                       & (1L << PRIVATE_FAX_NONSTANDARD))
2774       {
2775                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2776         {
2777                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2778                         plci->fax_connect_info_buffer[len++] = 0;
2779         }
2780                       else
2781                       {
2782           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2783             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2784    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2785           for (i = 0; i < fax_parms[7].length; i++)
2786      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2787                       }
2788                     }
2789                   }
2790                 }
2791                 else
2792                 {
2793                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2794                 }
2795                 fax_info_change = true;
2796 
2797               }
2798               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2799               {
2800                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2801                 fax_info_change = true;
2802               }
2803             }
2804             if (Info == GOOD)
2805             {
2806               plci->fax_connect_info_length = len;
2807               if (fax_info_change)
2808               {
2809                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2810                 {
2811                   start_internal_command (Id, plci, fax_connect_info_command);
2812                   return false;
2813                 }
2814                 else
2815                 {
2816                   start_internal_command (Id, plci, fax_adjust_b23_command);
2817                   return false;
2818                 }
2819               }
2820             }
2821           }
2822           else  Info = _WRONG_STATE;
2823         }
2824         else  Info = _WRONG_STATE;
2825       }
2826 
2827       else if (plci->B3_prot == B3_RTP)
2828       {
2829         plci->internal_req_buffer[0] = ncpi->length + 1;
2830         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2831         for (w = 0; w < ncpi->length; w++)
2832           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2833         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2834         return false;
2835       }
2836 
2837       if(!Info)
2838       {
2839         nl_req_ncci(plci,req,0);
2840         return 1;
2841       }
2842     }
2843   }
2844   else Info = _WRONG_IDENTIFIER;
2845 
2846   sendf(appl,
2847         _CONNECT_B3_R|CONFIRM,
2848         Id,
2849         Number,
2850         "w",Info);
2851   return false;
2852 }
2853 
2854 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2855                            PLCI *plci, APPL *appl, API_PARSE *parms)
2856 {
2857   word ncci;
2858   API_PARSE * ncpi;
2859   byte req;
2860 
2861   word w;
2862 
2863 
2864     API_PARSE fax_parms[9];
2865   word i;
2866   byte len;
2867 
2868 
2869   dbug(1,dprintf("connect_b3_res"));
2870 
2871   ncci = (word)(Id>>16);
2872   if(plci && ncci) {
2873     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2874       if (GET_WORD (&parms[0].info[0]) != 0)
2875       {
2876         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2877         channel_request_xon (plci, a->ncci_ch[ncci]);
2878         channel_xmit_xon (plci);
2879         cleanup_ncci_data (plci, ncci);
2880         nl_req_ncci(plci,N_DISC,(byte)ncci);
2881         return 1;
2882       }
2883       a->ncci_state[ncci] = INC_ACT_PENDING;
2884 
2885       req = N_CONNECT_ACK;
2886       ncpi = &parms[1];
2887       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2888       {
2889 
2890         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2891           & (1L << PRIVATE_FAX_NONSTANDARD))
2892  {
2893    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2894     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2895     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2896    {
2897             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2898             if (plci->fax_connect_info_length < len)
2899             {
2900               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2901               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2902             }
2903             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2904             {
2905               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2906             }
2907             else
2908             {
2909               if (plci->fax_connect_info_length <= len)
2910                 plci->fax_connect_info_buffer[len] = 0;
2911               len += 1 + plci->fax_connect_info_buffer[len];
2912               if (plci->fax_connect_info_length <= len)
2913                 plci->fax_connect_info_buffer[len] = 0;
2914               len += 1 + plci->fax_connect_info_buffer[len];
2915               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2916                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2917               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2918               for (i = 0; i < fax_parms[7].length; i++)
2919                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2920             }
2921             plci->fax_connect_info_length = len;
2922             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2923             start_internal_command (Id, plci, fax_connect_ack_command);
2924      return false;
2925           }
2926         }
2927 
2928         nl_req_ncci(plci,req,(byte)ncci);
2929         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2930          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2931         {
2932           if (plci->B3_prot == 4)
2933             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2934           else
2935             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2936           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2937         }
2938       }
2939 
2940       else if (plci->B3_prot == B3_RTP)
2941       {
2942         plci->internal_req_buffer[0] = ncpi->length + 1;
2943         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2944         for (w = 0; w < ncpi->length; w++)
2945           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2946         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2947         return false;
2948       }
2949 
2950       else
2951       {
2952         if(ncpi->length>2) {
2953           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2954           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2955         }
2956         nl_req_ncci(plci,req,(byte)ncci);
2957         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2958         if (plci->adjust_b_restore)
2959         {
2960           plci->adjust_b_restore = false;
2961           start_internal_command (Id, plci, adjust_b_restore);
2962         }
2963       }
2964       return 1;
2965     }
2966   }
2967   return false;
2968 }
2969 
2970 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2971                              PLCI *plci, APPL *appl, API_PARSE *parms)
2972 {
2973   word ncci;
2974 
2975   ncci = (word)(Id>>16);
2976   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2977 
2978   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2979    && (plci->State != OUTG_DIS_PENDING))
2980   {
2981     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2982       a->ncci_state[ncci] = CONNECTED;
2983       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2984       channel_request_xon (plci, a->ncci_ch[ncci]);
2985       channel_xmit_xon (plci);
2986     }
2987   }
2988   return false;
2989 }
2990 
2991 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2992                               PLCI *plci, APPL *appl, API_PARSE *parms)
2993 {
2994   word Info;
2995   word ncci;
2996   API_PARSE * ncpi;
2997 
2998   dbug(1,dprintf("disconnect_b3_req"));
2999 
3000   Info = _WRONG_IDENTIFIER;
3001   ncci = (word)(Id>>16);
3002   if (plci && ncci)
3003   {
3004     Info = _WRONG_STATE;
3005     if ((a->ncci_state[ncci] == CONNECTED)
3006      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3007      || (a->ncci_state[ncci] == INC_CON_PENDING)
3008      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3009     {
3010       a->ncci_state[ncci] = OUTG_DIS_PENDING;
3011       channel_request_xon (plci, a->ncci_ch[ncci]);
3012       channel_xmit_xon (plci);
3013 
3014       if (a->ncci[ncci].data_pending
3015        && ((plci->B3_prot == B3_TRANSPARENT)
3016         || (plci->B3_prot == B3_T30)
3017         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3018       {
3019         plci->send_disc = (byte)ncci;
3020         plci->command = 0;
3021         return false;
3022       }
3023       else
3024       {
3025         cleanup_ncci_data (plci, ncci);
3026 
3027         if(plci->B3_prot==2 || plci->B3_prot==3)
3028         {
3029           ncpi = &parms[0];
3030           if(ncpi->length>3)
3031           {
3032             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3033           }
3034         }
3035         nl_req_ncci(plci,N_DISC,(byte)ncci);
3036       }
3037       return 1;
3038     }
3039   }
3040   sendf(appl,
3041         _DISCONNECT_B3_R|CONFIRM,
3042         Id,
3043         Number,
3044         "w",Info);
3045   return false;
3046 }
3047 
3048 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3049                               PLCI *plci, APPL *appl, API_PARSE *parms)
3050 {
3051   word ncci;
3052   word i;
3053 
3054   ncci = (word)(Id>>16);
3055   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3056   if(plci && ncci) {
3057     plci->requested_options_conn = 0;
3058     plci->fax_connect_info_length = 0;
3059     plci->ncpi_state = 0x00;
3060     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3061       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3062     {
3063       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3064     }
3065     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3066     if(i<MAX_CHANNELS_PER_PLCI) {
3067       if(plci->channels)plci->channels--;
3068       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3069       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3070 
3071       ncci_free_receive_buffers (plci, ncci);
3072 
3073       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3074         if(plci->State == SUSPENDING){
3075           sendf(plci->appl,
3076                 _FACILITY_I,
3077                 Id & 0xffffL,
3078                 0,
3079                 "ws", (word)3, "\x03\x04\x00\x00");
3080           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3081         }
3082         plci_remove(plci);
3083         plci->State=IDLE;
3084       }
3085     }
3086     else
3087     {
3088       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3089        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3090        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3091       {
3092         ncci_free_receive_buffers (plci, ncci);
3093 
3094         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3095 
3096         plci->adapter->ncci_state[ncci] = IDLE;
3097         start_internal_command (Id, plci, fax_disconnect_command);
3098         return 1;
3099       }
3100     }
3101   }
3102   return false;
3103 }
3104 
3105 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3106                         PLCI *plci, APPL *appl, API_PARSE *parms)
3107 {
3108   NCCI   *ncci_ptr;
3109   DATA_B3_DESC   *data;
3110   word Info;
3111   word ncci;
3112   word i;
3113 
3114   dbug(1,dprintf("data_b3_req"));
3115 
3116   Info = _WRONG_IDENTIFIER;
3117   ncci = (word)(Id>>16);
3118   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3119 
3120   if (plci && ncci)
3121   {
3122     Info = _WRONG_STATE;
3123     if ((a->ncci_state[ncci] == CONNECTED)
3124      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3125     {
3126         /* queue data */
3127       ncci_ptr = &(a->ncci[ncci]);
3128       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3129       if (i >= MAX_DATA_B3)
3130         i -= MAX_DATA_B3;
3131       data = &(ncci_ptr->DBuffer[i]);
3132       data->Number = Number;
3133       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3134        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3135       {
3136 
3137         data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3138 
3139       }
3140       else
3141         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3142       data->Length = GET_WORD(parms[1].info);
3143       data->Handle = GET_WORD(parms[2].info);
3144       data->Flags = GET_WORD(parms[3].info);
3145       (ncci_ptr->data_pending)++;
3146 
3147         /* check for delivery confirmation */
3148       if (data->Flags & 0x0004)
3149       {
3150         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3151         if (i >= MAX_DATA_ACK)
3152           i -= MAX_DATA_ACK;
3153         ncci_ptr->DataAck[i].Number = data->Number;
3154         ncci_ptr->DataAck[i].Handle = data->Handle;
3155         (ncci_ptr->data_ack_pending)++;
3156       }
3157 
3158       send_data(plci);
3159       return false;
3160     }
3161   }
3162   if (appl)
3163   {
3164     if (plci)
3165     {
3166       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3167        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3168       {
3169 
3170         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3171 
3172       }
3173     }
3174     sendf(appl,
3175           _DATA_B3_R|CONFIRM,
3176           Id,
3177           Number,
3178           "ww",GET_WORD(parms[2].info),Info);
3179   }
3180   return false;
3181 }
3182 
3183 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3184                         PLCI *plci, APPL *appl, API_PARSE *parms)
3185 {
3186   word n;
3187   word ncci;
3188   word NCCIcode;
3189 
3190   dbug(1,dprintf("data_b3_res"));
3191 
3192   ncci = (word)(Id>>16);
3193   if(plci && ncci) {
3194     n = GET_WORD(parms[0].info);
3195     dbug(1,dprintf("free(%d)",n));
3196     NCCIcode = ncci | (((word) a->Id) << 8);
3197     if(n<appl->MaxBuffer &&
3198        appl->DataNCCI[n]==NCCIcode &&
3199        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3200       dbug(1,dprintf("found"));
3201       appl->DataNCCI[n] = 0;
3202 
3203       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3204         channel_request_xon (plci, a->ncci_ch[ncci]);
3205       }
3206       channel_xmit_xon (plci);
3207 
3208       if(appl->DataFlags[n] &4) {
3209         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3210         return 1;
3211       }
3212     }
3213   }
3214   return false;
3215 }
3216 
3217 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3218                          PLCI *plci, APPL *appl, API_PARSE *parms)
3219 {
3220   word Info;
3221   word ncci;
3222 
3223   dbug(1,dprintf("reset_b3_req"));
3224 
3225   Info = _WRONG_IDENTIFIER;
3226   ncci = (word)(Id>>16);
3227   if(plci && ncci)
3228   {
3229     Info = _WRONG_STATE;
3230     switch (plci->B3_prot)
3231     {
3232     case B3_ISO8208:
3233     case B3_X25_DCE:
3234       if(a->ncci_state[ncci]==CONNECTED)
3235       {
3236         nl_req_ncci(plci,N_RESET,(byte)ncci);
3237         send_req(plci);
3238         Info = GOOD;
3239       }
3240       break;
3241     case B3_TRANSPARENT:
3242       if(a->ncci_state[ncci]==CONNECTED)
3243       {
3244         start_internal_command (Id, plci, reset_b3_command);
3245         Info = GOOD;
3246       }
3247       break;
3248     }
3249   }
3250   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3251   sendf(appl,
3252         _RESET_B3_R|CONFIRM,
3253         Id,
3254         Number,
3255         "w",Info);
3256   return false;
3257 }
3258 
3259 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3260                          PLCI *plci, APPL *appl, API_PARSE *parms)
3261 {
3262   word ncci;
3263 
3264   dbug(1,dprintf("reset_b3_res"));
3265 
3266   ncci = (word)(Id>>16);
3267   if(plci && ncci) {
3268     switch (plci->B3_prot)
3269     {
3270     case B3_ISO8208:
3271     case B3_X25_DCE:
3272       if(a->ncci_state[ncci]==INC_RES_PENDING)
3273       {
3274         a->ncci_state[ncci] = CONNECTED;
3275         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3276         return true;
3277       }
3278     break;
3279     }
3280   }
3281   return false;
3282 }
3283 
3284 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3285                                  PLCI *plci, APPL *appl, API_PARSE *parms)
3286 {
3287   word ncci;
3288   API_PARSE * ncpi;
3289   byte req;
3290 
3291   dbug(1,dprintf("connect_b3_t90_a_res"));
3292 
3293   ncci = (word)(Id>>16);
3294   if(plci && ncci) {
3295     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3296       a->ncci_state[ncci] = CONNECTED;
3297     }
3298     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3299       a->ncci_state[ncci] = CONNECTED;
3300 
3301       req = N_CONNECT_ACK;
3302 
3303         /* parms[0]==0 for CAPI original message definition! */
3304       if(parms[0].info) {
3305         ncpi = &parms[1];
3306         if(ncpi->length>2) {
3307           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3308           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3309         }
3310       }
3311       nl_req_ncci(plci,req,(byte)ncci);
3312       return 1;
3313     }
3314   }
3315   return false;
3316 }
3317 
3318 
3319 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3320                          PLCI *plci, APPL *appl, API_PARSE *msg)
3321 {
3322   word Info=0;
3323   word i;
3324   byte tel;
3325     API_PARSE bp_parms[7];
3326 
3327   if(!plci || !msg)
3328   {
3329     Info = _WRONG_IDENTIFIER;
3330   }
3331   else
3332   {
3333     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3334                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3335     dbug(1,dprintf("PlciState=0x%x",plci->State));
3336     for(i=0;i<7;i++) bp_parms[i].length = 0;
3337 
3338     /* check if no channel is open, no B3 connected only */
3339     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3340      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3341     {
3342       Info = _WRONG_STATE;
3343     }
3344     /* check message format and fill bp_parms pointer */
3345     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3346     {
3347       Info = _WRONG_MESSAGE_FORMAT;
3348     }
3349     else
3350     {
3351       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3352       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3353         if(Id & EXT_CONTROLLER)
3354         {
3355           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3356           return 0;
3357         }
3358         plci->State=INC_CON_CONNECTED_ALERT;
3359         plci->appl = appl;
3360         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3361         dump_c_ind_mask (plci);
3362         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3363         {                         /* its quasi a connect        */
3364           if(test_c_ind_mask_bit (plci, i))
3365             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3366         }
3367       }
3368 
3369       api_save_msg(msg, "s", &plci->saved_msg);
3370       tel = plci->tel;
3371       if(Id & EXT_CONTROLLER)
3372       {
3373         if(tel) /* external controller in use by this PLCI */
3374         {
3375           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3376           {
3377             dbug(1,dprintf("Ext_Ctrl in use 1"));
3378             Info = _WRONG_STATE;
3379           }
3380         }
3381         else  /* external controller NOT in use by this PLCI ? */
3382         {
3383           if(a->AdvSignalPLCI)
3384           {
3385             dbug(1,dprintf("Ext_Ctrl in use 2"));
3386             Info = _WRONG_STATE;
3387           }
3388           else /* activate the codec */
3389           {
3390             dbug(1,dprintf("Ext_Ctrl start"));
3391             if(AdvCodecSupport(a, plci, appl, 0) )
3392             {
3393               dbug(1,dprintf("Error in codec procedures"));
3394               Info = _WRONG_STATE;
3395             }
3396             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3397             {
3398               plci->spoofed_msg = AWAITING_SELECT_B;
3399               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3400               plci->command = 0;
3401               dbug(1,dprintf("continue if codec loaded"));
3402               return false;
3403             }
3404           }
3405         }
3406       }
3407       else /* external controller bit is OFF */
3408       {
3409         if(tel) /* external controller in use, need to switch off */
3410         {
3411           if(a->AdvSignalAppl==appl)
3412           {
3413             CodecIdCheck(a, plci);
3414             plci->tel = 0;
3415             plci->adv_nl = 0;
3416             dbug(1,dprintf("Ext_Ctrl disable"));
3417           }
3418           else
3419           {
3420             dbug(1,dprintf("Ext_Ctrl not requested"));
3421           }
3422         }
3423       }
3424       if (!Info)
3425       {
3426         if (plci->call_dir & CALL_DIR_OUT)
3427           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3428         else if (plci->call_dir & CALL_DIR_IN)
3429           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3430         start_internal_command (Id, plci, select_b_command);
3431         return false;
3432       }
3433     }
3434   }
3435   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3436   return false;
3437 }
3438 
3439 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3440                              PLCI *plci, APPL *appl, API_PARSE *parms)
3441 {
3442   word command;
3443   word i;
3444   word ncci;
3445   API_PARSE * m;
3446     API_PARSE m_parms[5];
3447   word codec;
3448   byte req;
3449   byte ch;
3450   byte dir;
3451   static byte chi[2] = {0x01,0x00};
3452   static byte lli[2] = {0x01,0x00};
3453   static byte codec_cai[2] = {0x01,0x01};
3454   static byte null_msg = {0};
3455   static API_PARSE null_parms = { 0, &null_msg };
3456   PLCI   * v_plci;
3457   word Info=0;
3458 
3459   dbug(1,dprintf("manufacturer_req"));
3460   for(i=0;i<5;i++) m_parms[i].length = 0;
3461 
3462   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3463     Info = _WRONG_MESSAGE_FORMAT;
3464   }
3465   command = GET_WORD(parms[1].info);
3466   m = &parms[2];
3467   if (!Info)
3468   {
3469     switch(command) {
3470     case _DI_ASSIGN_PLCI:
3471       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3472         Info = _WRONG_MESSAGE_FORMAT;
3473         break;
3474       }
3475       codec = GET_WORD(m_parms[0].info);
3476       ch = m_parms[1].info[0];
3477       dir = m_parms[2].info[0];
3478       if((i=get_plci(a))) {
3479         plci = &a->plci[i-1];
3480         plci->appl = appl;
3481         plci->command = _MANUFACTURER_R;
3482         plci->m_command = command;
3483         plci->number = Number;
3484         plci->State = LOCAL_CONNECT;
3485         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3486         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3487 
3488         if((ch==1 || ch==2) && (dir<=2)) {
3489           chi[1] = (byte)(0x80|ch);
3490           lli[1] = 0;
3491           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3492           switch(codec)
3493           {
3494           case 0:
3495             Info = add_b1(plci,&m_parms[3],0,0);
3496             break;
3497           case 1:
3498             add_p(plci,CAI,codec_cai);
3499             break;
3500           /* manual 'swich on' to the codec support without signalling */
3501           /* first 'assign plci' with this function, then use */
3502           case 2:
3503             if(AdvCodecSupport(a, plci, appl, 0) ) {
3504               Info = _RESOURCE_ERROR;
3505             }
3506             else {
3507               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3508               lli[1] = 0x10; /* local call codec stream */
3509             }
3510             break;
3511           }
3512 
3513           plci->State = LOCAL_CONNECT;
3514           plci->manufacturer = true;
3515           plci->command = _MANUFACTURER_R;
3516           plci->m_command = command;
3517           plci->number = Number;
3518 
3519           if(!Info)
3520           {
3521             add_p(plci,LLI,lli);
3522             add_p(plci,CHI,chi);
3523             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3524             sig_req(plci,ASSIGN,DSIG_ID);
3525 
3526             if(!codec)
3527             {
3528               Info = add_b23(plci,&m_parms[3]);
3529               if(!Info)
3530               {
3531                 nl_req_ncci(plci,ASSIGN,0);
3532                 send_req(plci);
3533               }
3534             }
3535             if(!Info)
3536             {
3537               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3538               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3539               {
3540                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3541                 plci->spoofed_msg = AWAITING_MANUF_CON;
3542                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3543                 plci->command = 0;
3544                 send_req(plci);
3545                 return false;
3546               }
3547               if(dir==1) {
3548                 sig_req(plci,CALL_REQ,0);
3549               }
3550               else if(!dir){
3551                 sig_req(plci,LISTEN_REQ,0);
3552               }
3553               send_req(plci);
3554             }
3555             else
3556             {
3557               sendf(appl,
3558                     _MANUFACTURER_R|CONFIRM,
3559                     Id,
3560                     Number,
3561                     "dww",_DI_MANU_ID,command,Info);
3562               return 2;
3563             }
3564           }
3565         }
3566       }
3567       else  Info = _OUT_OF_PLCI;
3568       break;
3569 
3570     case _DI_IDI_CTRL:
3571       if(!plci)
3572       {
3573         Info = _WRONG_IDENTIFIER;
3574         break;
3575       }
3576       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3577         Info = _WRONG_MESSAGE_FORMAT;
3578         break;
3579       }
3580       req = m_parms[0].info[0];
3581       plci->command = _MANUFACTURER_R;
3582       plci->m_command = command;
3583       plci->number = Number;
3584       if(req==CALL_REQ)
3585       {
3586         plci->b_channel = getChannel(&m_parms[1]);
3587         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3588         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3589         {
3590           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3591           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3592           plci->command = 0;
3593           break;
3594         }
3595       }
3596       else if(req==LAW_REQ)
3597       {
3598         plci->cr_enquiry = true;
3599       }
3600       add_ss(plci,FTY,&m_parms[1]);
3601       sig_req(plci,req,0);
3602       send_req(plci);
3603       if(req==HANGUP)
3604       {      
3605         if (plci->NL.Id && !plci->nl_remove_id)
3606         {
3607           if (plci->channels)
3608           {
3609             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3610             {
3611               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3612               {
3613                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3614                 cleanup_ncci_data (plci, ncci);
3615                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3616               }
3617             }
3618           }
3619           mixer_remove (plci);
3620           nl_req_ncci(plci,REMOVE,0);
3621           send_req(plci);
3622         }  
3623       }
3624       break;
3625 
3626     case _DI_SIG_CTRL:
3627     /* signalling control for loop activation B-channel */
3628       if(!plci)
3629       {
3630         Info = _WRONG_IDENTIFIER;
3631         break;
3632       }
3633       if(m->length){
3634         plci->command = _MANUFACTURER_R;
3635         plci->number = Number;
3636         add_ss(plci,FTY,m);
3637         sig_req(plci,SIG_CTRL,0);
3638         send_req(plci);
3639       }
3640       else Info = _WRONG_MESSAGE_FORMAT;
3641       break;
3642 
3643     case _DI_RXT_CTRL:
3644     /* activation control for receiver/transmitter B-channel */
3645       if(!plci)
3646       {
3647         Info = _WRONG_IDENTIFIER;
3648         break;
3649       }
3650       if(m->length){
3651         plci->command = _MANUFACTURER_R;
3652         plci->number = Number;
3653         add_ss(plci,FTY,m);
3654         sig_req(plci,DSP_CTRL,0);
3655         send_req(plci);
3656       }
3657       else Info = _WRONG_MESSAGE_FORMAT;
3658       break;
3659 
3660     case _DI_ADV_CODEC:
3661     case _DI_DSP_CTRL:
3662       /* TEL_CTRL commands to support non standard adjustments: */
3663       /* Ring on/off, Handset micro volume, external micro vol. */
3664       /* handset+external speaker volume, receiver+transm. gain,*/
3665       /* handsfree on (hookinfo off), set mixer command         */
3666 
3667       if(command == _DI_ADV_CODEC)
3668       {
3669         if(!a->AdvCodecPLCI) {
3670           Info = _WRONG_STATE;
3671           break;
3672         }
3673         v_plci = a->AdvCodecPLCI;
3674       }
3675       else
3676       {
3677         if (plci
3678          && (m->length >= 3)
3679          && (m->info[1] == 0x1c)
3680          && (m->info[2] >= 1))
3681         {
3682           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3683           {
3684             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3685             {
3686               Info = _WRONG_STATE;
3687               break;
3688             }
3689             a->adv_voice_coef_length = m->info[2] - 1;
3690             if (a->adv_voice_coef_length > m->length - 3)
3691               a->adv_voice_coef_length = (byte)(m->length - 3);
3692             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3693               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3694             for (i = 0; i < a->adv_voice_coef_length; i++)
3695               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3696             if (plci->B1_facilities & B1_FACILITY_VOICE)
3697               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3698             break;
3699           }
3700           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3701           {
3702             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3703             {
3704               Info = _FACILITY_NOT_SUPPORTED;
3705               break;
3706             }
3707 
3708             plci->dtmf_parameter_length = m->info[2] - 1;
3709             if (plci->dtmf_parameter_length > m->length - 3)
3710               plci->dtmf_parameter_length = (byte)(m->length - 3);
3711             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3712               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3713             for (i = 0; i < plci->dtmf_parameter_length; i++)
3714               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3715             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3716               dtmf_parameter_write (plci);
3717             break;
3718 
3719           }
3720         }
3721         v_plci = plci;
3722       }
3723 
3724       if(!v_plci)
3725       {
3726         Info = _WRONG_IDENTIFIER;
3727         break;
3728       }
3729       if(m->length){
3730         add_ss(v_plci,FTY,m);
3731         sig_req(v_plci,TEL_CTRL,0);
3732         send_req(v_plci);
3733       }
3734       else Info = _WRONG_MESSAGE_FORMAT;
3735 
3736       break;
3737 
3738     case _DI_OPTIONS_REQUEST:
3739       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3740         Info = _WRONG_MESSAGE_FORMAT;
3741         break;
3742       }
3743       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3744       {
3745         Info = _FACILITY_NOT_SUPPORTED;
3746         break;
3747       }
3748       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3749       break;
3750 
3751 
3752 
3753     default:
3754       Info = _WRONG_MESSAGE_FORMAT;
3755       break;
3756     }
3757   }
3758 
3759   sendf(appl,
3760         _MANUFACTURER_R|CONFIRM,
3761         Id,
3762         Number,
3763         "dww",_DI_MANU_ID,command,Info);
3764   return false;
3765 }
3766 
3767 
3768 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3769                              PLCI *plci, APPL *appl, API_PARSE *msg)
3770 {
3771   word indication;
3772 
3773     API_PARSE m_parms[3];
3774   API_PARSE *ncpi;
3775     API_PARSE fax_parms[9];
3776   word i;
3777   byte len;
3778 
3779 
3780   dbug(1,dprintf("manufacturer_res"));
3781 
3782   if ((msg[0].length == 0)
3783    || (msg[1].length == 0)
3784    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3785   {
3786     return false;
3787   }
3788   indication = GET_WORD(msg[1].info);
3789   switch (indication)
3790   {
3791 
3792   case _DI_NEGOTIATE_B3:
3793     if(!plci)
3794       break;
3795     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3796      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3797     {
3798       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3799       break;
3800     }
3801     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3802     {
3803       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3804       break;
3805     }
3806     ncpi = &m_parms[1];
3807     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3808     if (plci->fax_connect_info_length < len)
3809     {
3810       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3811       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3812     }
3813     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3814     {
3815       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3816     }
3817     else
3818     {
3819       if (plci->fax_connect_info_length <= len)
3820         plci->fax_connect_info_buffer[len] = 0;
3821       len += 1 + plci->fax_connect_info_buffer[len];
3822       if (plci->fax_connect_info_length <= len)
3823         plci->fax_connect_info_buffer[len] = 0;
3824       len += 1 + plci->fax_connect_info_buffer[len];
3825       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3826         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3827       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3828       for (i = 0; i < fax_parms[7].length; i++)
3829         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3830     }
3831     plci->fax_connect_info_length = len;
3832     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3833     start_internal_command (Id, plci, fax_edata_ack_command);
3834     break;
3835 
3836   }
3837   return false;
3838 }
3839 
3840 /*------------------------------------------------------------------*/
3841 /* IDI callback function                                            */
3842 /*------------------------------------------------------------------*/
3843 
3844 void   callback(ENTITY   * e)
3845 {
3846   DIVA_CAPI_ADAPTER   * a;
3847   APPL   * appl;
3848   PLCI   * plci;
3849   CAPI_MSG   *m;
3850   word i, j;
3851   byte rc;
3852   byte ch;
3853   byte req;
3854   byte global_req;
3855   int no_cancel_rc;
3856 
3857   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3858                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3859 
3860   a = &(adapter[(byte)e->user[0]]);
3861   plci = &(a->plci[e->user[1]]);
3862   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3863 
3864   /*
3865      If new protocol code and new XDI is used then CAPI should work
3866      fully in accordance with IDI cpec an look on callback field instead
3867      of Rc field for return codes.
3868    */
3869   if (((e->complete == 0xff) && no_cancel_rc) ||
3870       (e->Rc && !no_cancel_rc)) {
3871     rc = e->Rc;
3872     ch = e->RcCh;
3873     req = e->Req;
3874     e->Rc = 0;
3875 
3876     if (e->user[0] & 0x8000)
3877     {
3878       /*
3879          If REMOVE request was sent then we have to wait until
3880          return code with Id set to zero arrives.
3881          All other return codes should be ignored.
3882          */
3883       if (req == REMOVE)
3884       {
3885         if (e->Id)
3886         {
3887           dbug(1,dprintf("cancel RC in REMOVE state"));
3888           return;
3889         }
3890         channel_flow_control_remove (plci);
3891         for (i = 0; i < 256; i++)
3892         {
3893           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3894             a->FlowControlIdTable[i] = 0;
3895         }
3896         plci->nl_remove_id = 0;
3897         if (plci->rx_dma_descriptor > 0) {
3898           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3899           plci->rx_dma_descriptor = 0;
3900         }
3901       }
3902       if (rc == OK_FC)
3903       {
3904         a->FlowControlIdTable[ch] = e->Id;
3905         a->FlowControlSkipTable[ch] = 0;
3906 
3907         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3908         a->ch_flow_plci[ch] = plci->Id;
3909         plci->nl_req = 0;
3910       }
3911       else
3912       {
3913         /*
3914           Cancel return codes self, if feature was requested
3915           */
3916         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3917           a->FlowControlIdTable[ch] = 0;
3918           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3919             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3920             return;
3921           }
3922         }
3923 
3924         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3925         {
3926           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3927           if (ch == e->ReqCh)
3928             plci->nl_req = 0;
3929         }
3930         else
3931           plci->nl_req = 0;
3932       }
3933       if (plci->nl_req)
3934         control_rc (plci, 0, rc, ch, 0, true);
3935       else
3936       {
3937         if (req == N_XON)
3938         {
3939           channel_x_on (plci, ch);
3940           if (plci->internal_command)
3941             control_rc (plci, req, rc, ch, 0, true);
3942         }
3943         else
3944         {
3945           if (plci->nl_global_req)
3946           {
3947             global_req = plci->nl_global_req;
3948             plci->nl_global_req = 0;
3949             if (rc != ASSIGN_OK) {
3950               e->Id = 0;
3951               if (plci->rx_dma_descriptor > 0) {
3952                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3953                 plci->rx_dma_descriptor = 0;
3954               }
3955             }
3956             channel_xmit_xon (plci);
3957             control_rc (plci, 0, rc, ch, global_req, true);
3958           }
3959           else if (plci->data_sent)
3960           {
3961             channel_xmit_xon (plci);
3962             plci->data_sent = false;
3963             plci->NL.XNum = 1;
3964             data_rc (plci, ch);
3965             if (plci->internal_command)
3966               control_rc (plci, req, rc, ch, 0, true);
3967           }
3968           else
3969           {
3970             channel_xmit_xon (plci);
3971             control_rc (plci, req, rc, ch, 0, true);
3972           }
3973         }
3974       }
3975     }
3976     else
3977     {
3978       /*
3979          If REMOVE request was sent then we have to wait until
3980          return code with Id set to zero arrives.
3981          All other return codes should be ignored.
3982          */
3983       if (req == REMOVE)
3984       {
3985         if (e->Id)
3986         {
3987           dbug(1,dprintf("cancel RC in REMOVE state"));
3988           return;
3989         }
3990         plci->sig_remove_id = 0;
3991       }
3992       plci->sig_req = 0;
3993       if (plci->sig_global_req)
3994       {
3995         global_req = plci->sig_global_req;
3996         plci->sig_global_req = 0;
3997         if (rc != ASSIGN_OK)
3998           e->Id = 0;
3999         channel_xmit_xon (plci);
4000         control_rc (plci, 0, rc, ch, global_req, false);
4001       }
4002       else
4003       {
4004         channel_xmit_xon (plci);
4005         control_rc (plci, req, rc, ch, 0, false);
4006       }
4007     }
4008     /*
4009       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4010       same callback. Also if new XDI and protocol code used then jump
4011       direct to finish.
4012       */
4013     if (no_cancel_rc) {
4014       channel_xmit_xon(plci);
4015       goto capi_callback_suffix;
4016     }
4017   }
4018 
4019   channel_xmit_xon(plci);
4020 
4021   if (e->Ind) {
4022     if (e->user[0] &0x8000) {
4023       byte Ind = e->Ind & 0x0f;
4024       byte Ch = e->IndCh;
4025       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4026           (a->ch_flow_plci[Ch] == plci->Id)) {
4027         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4028           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4029         }
4030         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4031       }
4032       nl_ind(plci);
4033       if ((e->RNR != 1) &&
4034           (a->ch_flow_plci[Ch] == plci->Id) &&
4035           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4036         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4037         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4038       }
4039     } else {
4040       sig_ind(plci);
4041     }
4042     e->Ind = 0;
4043   }
4044 
4045 capi_callback_suffix:
4046 
4047   while (!plci->req_in
4048    && !plci->internal_command
4049    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4050   {
4051     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4052 
4053     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4054 
4055     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4056     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4057     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4058       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4059     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4060     {
4061       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4062       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4063     }
4064     else
4065     {
4066       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4067     }
4068     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4069     {
4070       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4071       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4072     }
4073     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4074     {
4075       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4076       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4077     }
4078     i = api_put (appl, m);
4079     if (i != 0)
4080     {
4081       if (m->header.command == _DATA_B3_R)
4082 
4083         TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4084 
4085       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4086       break;
4087     }
4088 
4089     if (plci->li_notify_update)
4090     {
4091       plci->li_notify_update = false;
4092       mixer_notify_update (plci, false);
4093     }
4094 
4095   }
4096   send_data(plci);
4097   send_req(plci);
4098 }
4099 
4100 
4101 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4102                        byte nl_rc)
4103 {
4104   dword Id;
4105   dword rId;
4106   word Number;
4107   word Info=0;
4108   word i;
4109   word ncci;
4110   DIVA_CAPI_ADAPTER   * a;
4111   APPL   * appl;
4112   PLCI   * rplci;
4113     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4114     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4115 
4116   if (!plci) {
4117     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4118     return;
4119   }
4120   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4121   if(plci->req_in!=plci->req_out)
4122   {
4123     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4124     {
4125       dbug(1,dprintf("req_1return"));
4126       return;
4127     }
4128     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4129   }
4130   plci->req_in = plci->req_in_start = plci->req_out = 0;
4131   dbug(1,dprintf("control_rc"));
4132 
4133   appl = plci->appl;
4134   a = plci->adapter;
4135   ncci = a->ch_ncci[ch];
4136   if(appl)
4137   {
4138     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4139     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4140     Number = plci->number;
4141     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));
4142     dbug(1,dprintf("channels=0x%x",plci->channels));
4143     if (plci_remove_check(plci))
4144       return;
4145     if(req==REMOVE && rc==ASSIGN_OK)
4146     {
4147       sig_req(plci,HANGUP,0);
4148       sig_req(plci,REMOVE,0);
4149       send_req(plci);
4150     }
4151     if(plci->command)
4152     {
4153       switch(plci->command)
4154       {
4155       case C_HOLD_REQ:
4156         dbug(1,dprintf("HoldRC=0x%x",rc));
4157         SSparms[1] = (byte)S_HOLD;
4158         if(rc!=OK)
4159         {
4160           plci->SuppState = IDLE;
4161           Info = 0x2001;
4162         }
4163         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4164         break;
4165 
4166       case C_RETRIEVE_REQ:
4167         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4168         SSparms[1] = (byte)S_RETRIEVE;
4169         if(rc!=OK)
4170         {
4171           plci->SuppState = CALL_HELD;
4172           Info = 0x2001;
4173         }
4174         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4175         break;
4176 
4177       case _INFO_R:
4178         dbug(1,dprintf("InfoRC=0x%x",rc));
4179         if(rc!=OK) Info=_WRONG_STATE;
4180         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4181         break;
4182 
4183       case _CONNECT_R:
4184         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4185         if (plci->State == INC_DIS_PENDING)
4186           break;
4187         if(plci->Sig.Id!=0xff)
4188         {
4189           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4190            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4191           {
4192             dbug(1,dprintf("No more IDs/Call_Req failed"));
4193             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4194             plci_remove(plci);
4195             plci->State = IDLE;
4196             break;
4197           }
4198           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4199           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4200         }
4201         else /* D-ch activation */
4202         {
4203           if (rc != ASSIGN_OK)
4204           {
4205             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4206             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4207             plci_remove(plci);
4208             plci->State = IDLE;
4209             break;
4210           }
4211           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4212           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4213           plci->State = INC_ACT_PENDING;
4214         }
4215         break;
4216 
4217       case _CONNECT_I|RESPONSE:
4218         if (plci->State != INC_DIS_PENDING)
4219           plci->State = INC_CON_ACCEPT;
4220         break;
4221 
4222       case _DISCONNECT_R:
4223         if (plci->State == INC_DIS_PENDING)
4224           break;
4225         if(plci->Sig.Id!=0xff)
4226         {
4227           plci->State = OUTG_DIS_PENDING;
4228           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4229         }
4230         break;
4231 
4232       case SUSPEND_REQ:
4233         break;
4234 
4235       case RESUME_REQ:
4236         break;
4237 
4238       case _CONNECT_B3_R:
4239         if(rc!=OK)
4240         {
4241           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4242           break;
4243         }
4244         ncci = get_ncci (plci, ch, 0);
4245         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4246         plci->channels++;
4247         if(req==N_RESET)
4248         {
4249           a->ncci_state[ncci] = INC_ACT_PENDING;
4250           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4251           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4252         }
4253         else
4254         {
4255           a->ncci_state[ncci] = OUTG_CON_PENDING;
4256           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4257         }
4258         break;
4259 
4260       case _CONNECT_B3_I|RESPONSE:
4261         break;
4262 
4263       case _RESET_B3_R:
4264 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4265         break;
4266 
4267       case _DISCONNECT_B3_R:
4268         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4269         break;
4270 
4271       case _MANUFACTURER_R:
4272         break;
4273 
4274       case PERM_LIST_REQ:
4275         if(rc!=OK)
4276         {
4277           Info = _WRONG_IDENTIFIER;
4278           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4279           plci_remove(plci);
4280         }
4281         else
4282           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4283         break;
4284 
4285       default:
4286         break;
4287       }
4288       plci->command = 0;
4289     }
4290     else if (plci->internal_command)
4291     {
4292       switch(plci->internal_command)
4293       {
4294       case BLOCK_PLCI:
4295         return;
4296 
4297       case GET_MWI_STATE:
4298         if(rc==OK) /* command supported, wait for indication */
4299         {
4300           return;
4301         }
4302         plci_remove(plci);
4303         break;
4304 
4305         /* Get Supported Services */
4306       case GETSERV_REQ_PEND:
4307         if(rc==OK) /* command supported, wait for indication */
4308         {
4309           break;
4310         }
4311         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4312         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4313         plci_remove(plci);
4314         break;
4315 
4316       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4317       case INTERR_NUMBERS_REQ_PEND:
4318       case CF_START_PEND:                  /* Call Forwarding Start pending */
4319       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4320       case CCBS_REQUEST_REQ_PEND:
4321       case CCBS_DEACTIVATE_REQ_PEND:
4322       case CCBS_INTERROGATE_REQ_PEND:
4323         switch(plci->internal_command)
4324         {
4325           case INTERR_DIVERSION_REQ_PEND:
4326             SSparms[1] = S_INTERROGATE_DIVERSION;
4327             break;
4328           case INTERR_NUMBERS_REQ_PEND:
4329             SSparms[1] = S_INTERROGATE_NUMBERS;
4330             break;
4331           case CF_START_PEND:
4332             SSparms[1] = S_CALL_FORWARDING_START;
4333             break;
4334           case CF_STOP_PEND:
4335             SSparms[1] = S_CALL_FORWARDING_STOP;
4336             break;
4337           case CCBS_REQUEST_REQ_PEND:
4338             SSparms[1] = S_CCBS_REQUEST;
4339             break;
4340           case CCBS_DEACTIVATE_REQ_PEND:
4341             SSparms[1] = S_CCBS_DEACTIVATE;
4342             break;
4343           case CCBS_INTERROGATE_REQ_PEND:
4344             SSparms[1] = S_CCBS_INTERROGATE;
4345             break;
4346         }
4347         if(global_req==ASSIGN)
4348         {
4349           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4350           return;
4351         }
4352         if(!plci->appl) break;
4353         if(rc==ISDN_GUARD_REJ)
4354         {
4355           Info = _CAPI_GUARD_ERROR;
4356         }
4357         else if(rc!=OK)
4358         {
4359           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4360         }
4361         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4362               plci->number,"wws",Info,(word)3,SSparms);
4363         if(Info) plci_remove(plci);
4364         break;
4365 
4366         /* 3pty conference pending */
4367       case PTY_REQ_PEND:
4368         if(!plci->relatedPTYPLCI) break;
4369         rplci = plci->relatedPTYPLCI;
4370         SSparms[1] = plci->ptyState;
4371         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4372         if(rplci->tel) rId|=EXT_CONTROLLER;
4373         if(rc!=OK)
4374         {
4375           Info = 0x300E; /* not supported */
4376           plci->relatedPTYPLCI = NULL;
4377           plci->ptyState = 0;
4378         }
4379         sendf(rplci->appl,
4380               _FACILITY_R|CONFIRM,
4381               rId,
4382               plci->number,
4383               "wws",Info,(word)3,SSparms);
4384         break;
4385 
4386         /* Explicit Call Transfer pending */
4387       case ECT_REQ_PEND:
4388         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4389         if(!plci->relatedPTYPLCI) break;
4390         rplci = plci->relatedPTYPLCI;
4391         SSparms[1] = S_ECT;
4392         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4393         if(rplci->tel) rId|=EXT_CONTROLLER;
4394         if(rc!=OK)
4395         {
4396           Info = 0x300E; /* not supported */
4397           plci->relatedPTYPLCI = NULL;
4398           plci->ptyState = 0;
4399         }
4400         sendf(rplci->appl,
4401               _FACILITY_R|CONFIRM,
4402               rId,
4403               plci->number,
4404               "wws",Info,(word)3,SSparms);
4405         break;
4406 
4407       case _MANUFACTURER_R:
4408         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4409         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4410         {
4411           dbug(1,dprintf("No more IDs"));
4412           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4413           plci_remove(plci);  /* after codec init, internal codec commands pending */
4414         }
4415         break;
4416 
4417       case _CONNECT_R:
4418         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4419         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4420         {
4421           dbug(1,dprintf("No more IDs"));
4422           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4423           plci_remove(plci);  /* after codec init, internal codec commands pending */
4424         }
4425         break;
4426 
4427       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4428         return;
4429 
4430       case PERM_COD_CALL:
4431         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4432         plci->internal_command = PERM_COD_CONN_PEND;
4433         return;
4434 
4435       case PERM_COD_ASSIGN:
4436         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4437         if(rc!=ASSIGN_OK) break;
4438         sig_req(plci,CALL_REQ,0);
4439         send_req(plci);
4440         plci->internal_command = PERM_COD_CALL;
4441         return;
4442 
4443         /* Null Call Reference Request pending */
4444       case C_NCR_FAC_REQ:
4445         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4446         if(global_req==ASSIGN)
4447         {
4448           if(rc==ASSIGN_OK)
4449           {
4450             return;
4451           }
4452           else
4453           {
4454             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4455             appl->NullCREnable = false;
4456             plci_remove(plci);
4457           }
4458         }
4459         else if(req==NCR_FACILITY)
4460         {
4461           if(rc==OK)
4462           {
4463             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4464           }
4465           else
4466           {
4467             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4468             appl->NullCREnable = false;
4469           }
4470           plci_remove(plci);
4471         }
4472         break;
4473 
4474       case HOOK_ON_REQ:
4475         if(plci->channels)
4476         {
4477           if(a->ncci_state[ncci]==CONNECTED)
4478           {
4479             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4480             cleanup_ncci_data (plci, ncci);
4481             nl_req_ncci(plci,N_DISC,(byte)ncci);
4482           }
4483           break;
4484         }
4485         break;
4486 
4487       case HOOK_OFF_REQ:
4488         if (plci->State == INC_DIS_PENDING)
4489           break;
4490         sig_req(plci,CALL_REQ,0);
4491         send_req(plci);
4492         plci->State=OUTG_CON_PENDING;
4493         break;
4494 
4495 
4496       case MWI_ACTIVATE_REQ_PEND:
4497       case MWI_DEACTIVATE_REQ_PEND:
4498         if(global_req == ASSIGN && rc==ASSIGN_OK)
4499         {
4500           dbug(1,dprintf("MWI_REQ assigned"));
4501           return;
4502         }
4503         else if(rc!=OK)
4504         {                 
4505           if(rc==WRONG_IE)
4506           {
4507             Info = 0x2007; /* Illegal message parameter coding */
4508             dbug(1,dprintf("MWI_REQ invalid parameter"));
4509           }
4510           else
4511           {
4512             Info = 0x300B; /* not supported */                      
4513             dbug(1,dprintf("MWI_REQ not supported"));
4514           }
4515           /* 0x3010: Request not allowed in this state */
4516           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4517                     
4518         }
4519         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4520         {
4521           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4522         }
4523         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4524 
4525         if(plci->cr_enquiry)
4526         {
4527           sendf(plci->appl,
4528                 _FACILITY_R|CONFIRM,
4529                 Id&0xf,
4530                 plci->number,
4531                 "wws",Info,(word)3,SSparms);
4532           if(rc!=OK) plci_remove(plci);
4533         }
4534         else
4535         {
4536           sendf(plci->appl,
4537                 _FACILITY_R|CONFIRM,
4538                 Id,
4539                 plci->number,
4540                 "wws",Info,(word)3,SSparms);
4541         }
4542         break;
4543 
4544       case CONF_BEGIN_REQ_PEND:
4545       case CONF_ADD_REQ_PEND:
4546       case CONF_SPLIT_REQ_PEND:
4547       case CONF_DROP_REQ_PEND:
4548       case CONF_ISOLATE_REQ_PEND:
4549       case CONF_REATTACH_REQ_PEND:
4550         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4551         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4552         rplci = plci;
4553         rId = Id;
4554         switch(plci->internal_command)
4555         {
4556           case CONF_BEGIN_REQ_PEND:
4557             SSparms[1] = S_CONF_BEGIN;
4558             break;
4559           case CONF_ADD_REQ_PEND:
4560             SSparms[1] = S_CONF_ADD;
4561             rplci = plci->relatedPTYPLCI;
4562             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4563             break;
4564           case CONF_SPLIT_REQ_PEND:
4565             SSparms[1] = S_CONF_SPLIT;
4566             break;
4567           case CONF_DROP_REQ_PEND:
4568             SSparms[1] = S_CONF_DROP;
4569             break;
4570           case CONF_ISOLATE_REQ_PEND:
4571             SSparms[1] = S_CONF_ISOLATE;
4572             break;
4573           case CONF_REATTACH_REQ_PEND:
4574             SSparms[1] = S_CONF_REATTACH;
4575             break;
4576         }
4577         
4578         if(rc!=OK)
4579         {
4580           Info = 0x300E; /* not supported */
4581           plci->relatedPTYPLCI = NULL;
4582           plci->ptyState = 0;
4583         }
4584         sendf(rplci->appl,
4585               _FACILITY_R|CONFIRM,
4586               rId,
4587               plci->number,
4588               "wws",Info,(word)3,SSparms);
4589         break;
4590 
4591       case VSWITCH_REQ_PEND:
4592         if(rc!=OK)
4593         {
4594           if(plci->relatedPTYPLCI)
4595           {
4596             plci->relatedPTYPLCI->vswitchstate=0;
4597             plci->relatedPTYPLCI->vsprot=0;
4598             plci->relatedPTYPLCI->vsprotdialect=0;    
4599           }
4600           plci->vswitchstate=0;
4601           plci->vsprot=0;
4602           plci->vsprotdialect=0;
4603         }
4604         else
4605         {
4606           if(plci->relatedPTYPLCI &&
4607              plci->vswitchstate==1 &&
4608              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4609             plci->vswitchstate=3;
4610         }
4611         break;
4612 
4613   /* Call Deflection Request pending (SSCT) */
4614       case CD_REQ_PEND:
4615         SSparms[1] = S_CALL_DEFLECTION;
4616         if(rc!=OK)
4617         {
4618           Info = 0x300E; /* not supported */
4619           plci->appl->CDEnable = 0;
4620         }  
4621         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4622           plci->number,"wws",Info,(word)3,SSparms);
4623         break;
4624 
4625       case RTP_CONNECT_B3_REQ_COMMAND_2:
4626         if (rc == OK)
4627         {
4628           ncci = get_ncci (plci, ch, 0);
4629           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4630           plci->channels++;
4631           a->ncci_state[ncci] = OUTG_CON_PENDING;
4632         }
4633 
4634       default:
4635         if (plci->internal_command_queue[0])
4636         {
4637           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4638           if (plci->internal_command)
4639             return;
4640         }
4641         break;
4642       }
4643       next_internal_command (Id, plci);
4644     }
4645   }
4646   else /* appl==0 */
4647   {
4648     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4649     if(plci->tel) Id|=EXT_CONTROLLER;
4650 
4651     switch(plci->internal_command)
4652     {
4653     case BLOCK_PLCI:
4654       return;
4655 
4656     case START_L1_SIG_ASSIGN_PEND:
4657     case REM_L1_SIG_ASSIGN_PEND:
4658       if(global_req == ASSIGN)
4659       {
4660         break;
4661       }
4662       else
4663       {
4664         dbug(1,dprintf("***L1 Req rem PLCI"));
4665         plci->internal_command = 0;
4666         sig_req(plci,REMOVE,0);
4667         send_req(plci);
4668       }
4669       break;
4670 
4671       /* Call Deflection Request pending, just no appl ptr assigned */
4672     case CD_REQ_PEND:
4673       SSparms[1] = S_CALL_DEFLECTION;
4674       if(rc!=OK)
4675       {
4676         Info = 0x300E; /* not supported */
4677       }
4678       for(i=0; i<max_appl; i++)
4679       {
4680         if(application[i].CDEnable)
4681         {
4682           if(!application[i].Id) application[i].CDEnable = 0;
4683           else
4684           {
4685             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4686                   plci->number,"wws",Info,(word)3,SSparms);
4687             if(Info) application[i].CDEnable = 0;
4688           }
4689         }
4690       }
4691       plci->internal_command = 0;
4692       break;
4693 
4694     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4695       return;
4696 
4697     case PERM_COD_CALL:
4698       plci->internal_command = PERM_COD_CONN_PEND;
4699       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4700       return;
4701 
4702     case PERM_COD_ASSIGN:
4703       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4704       plci->internal_command = 0;
4705       if(rc!=ASSIGN_OK) break;
4706       plci->internal_command = PERM_COD_CALL;
4707       sig_req(plci,CALL_REQ,0);
4708       send_req(plci);
4709       return;
4710 
4711     case LISTEN_SIG_ASSIGN_PEND:
4712       if(rc == ASSIGN_OK)
4713       {
4714         plci->internal_command = 0;
4715         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4716         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4717         sig_req(plci,INDICATE_REQ,0);
4718         send_req(plci);
4719       }
4720       else
4721       {
4722         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4723         a->listen_active--;
4724         plci_remove(plci);
4725         plci->State = IDLE;
4726       }
4727       break;
4728 
4729     case USELAW_REQ:
4730       if(global_req == ASSIGN)
4731       {
4732         if (rc==ASSIGN_OK)
4733       {
4734         sig_req(plci,LAW_REQ,0);
4735         send_req(plci);
4736         dbug(1,dprintf("Auto-Law assigned"));
4737         }
4738         else
4739         {
4740           dbug(1,dprintf("Auto-Law assign failed"));
4741           a->automatic_law = 3;
4742           plci->internal_command = 0;
4743           a->automatic_lawPLCI = NULL;
4744         }
4745         break;
4746       }
4747       else if(req == LAW_REQ && rc==OK)
4748       {
4749         dbug(1,dprintf("Auto-Law initiated"));
4750         a->automatic_law = 2;
4751         plci->internal_command = 0;
4752       }
4753       else
4754       {
4755         dbug(1,dprintf("Auto-Law not supported"));
4756         a->automatic_law = 3;
4757         plci->internal_command = 0;
4758         sig_req(plci,REMOVE,0);
4759         send_req(plci);
4760         a->automatic_lawPLCI = NULL;
4761       }
4762       break;
4763     }
4764     plci_remove_check(plci);
4765   }
4766 }
4767 
4768 static void data_rc(PLCI *plci, byte ch)
4769 {
4770   dword Id;
4771   DIVA_CAPI_ADAPTER   * a;
4772   NCCI   *ncci_ptr;
4773   DATA_B3_DESC   *data;
4774   word ncci;
4775 
4776   if (plci->appl)
4777   {
4778     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4779     a = plci->adapter;
4780     ncci = a->ch_ncci[ch];
4781     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4782     {
4783       ncci_ptr = &(a->ncci[ncci]);
4784       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4785       if (ncci_ptr->data_pending)
4786       {
4787         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4788         if (!(data->Flags &4) && a->ncci_state[ncci])
4789         {
4790           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4791           if(plci->tel) Id|=EXT_CONTROLLER;
4792           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4793                 "ww",data->Handle,0);
4794         }
4795         (ncci_ptr->data_out)++;
4796         if (ncci_ptr->data_out == MAX_DATA_B3)
4797           ncci_ptr->data_out = 0;
4798         (ncci_ptr->data_pending)--;
4799       }
4800     }
4801   }
4802 }
4803 
4804 static void data_ack(PLCI *plci, byte ch)
4805 {
4806   dword Id;
4807   DIVA_CAPI_ADAPTER   * a;
4808   NCCI   *ncci_ptr;
4809   word ncci;
4810 
4811   a = plci->adapter;
4812   ncci = a->ch_ncci[ch];
4813   ncci_ptr = &(a->ncci[ncci]);
4814   if (ncci_ptr->data_ack_pending)
4815   {
4816     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4817     {
4818       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4819       if(plci->tel) Id|=EXT_CONTROLLER;
4820       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4821             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4822     }
4823     (ncci_ptr->data_ack_out)++;
4824     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4825       ncci_ptr->data_ack_out = 0;
4826     (ncci_ptr->data_ack_pending)--;
4827   }
4828 }
4829 
4830 static void sig_ind(PLCI *plci)
4831 {
4832   dword x_Id;
4833   dword Id;
4834   dword rId;
4835   word Number = 0;
4836   word i;
4837   word cip;
4838   dword cip_mask;
4839   byte   *ie;
4840   DIVA_CAPI_ADAPTER   * a;
4841     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4842 #define MAXPARMSIDS 31
4843     byte   * parms[MAXPARMSIDS];
4844     byte   * add_i[4];
4845     byte   * multi_fac_parms[MAX_MULTI_IE];
4846     byte   * multi_pi_parms [MAX_MULTI_IE];
4847     byte   * multi_ssext_parms [MAX_MULTI_IE];
4848     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4849 
4850     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4851 
4852   byte ai_len;
4853     byte   *esc_chi = "";
4854     byte   *esc_law = "";
4855     byte   *pty_cai = "";
4856     byte   *esc_cr  = "";
4857     byte   *esc_profile = "";
4858 
4859     byte facility[256];
4860   PLCI   * tplci = NULL;
4861   byte chi[] = "\x02\x18\x01";
4862   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4863     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4864   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4865   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4866   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4867   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4868     word parms_id[] =
4869          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4870           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4871           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4872           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4873           /* 14 FTY repl by ESC_CHI */
4874           /* 18 PI  repl by ESC_LAW */
4875          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4876      word multi_fac_id[] = {1, FTY};
4877      word multi_pi_id[]  = {1, PI};
4878      word multi_CiPN_id[]  = {1, OAD};
4879      word multi_ssext_id[]  = {1, ESC_SSEXT};
4880 
4881      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4882 
4883   byte   * cau;
4884   word ncci;
4885     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4886     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4887     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4888     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4889   byte force_mt_info = false;
4890   byte dir;
4891   dword d;
4892   word w;
4893 
4894   a = plci->adapter;
4895   Id = ((word)plci->Id<<8)|a->Id;
4896   PUT_WORD(&SS_Ind[4],0x0000);
4897 
4898   if (plci->sig_remove_id)
4899   {
4900     plci->Sig.RNR = 2; /* discard */
4901     dbug(1,dprintf("SIG discard while remove pending"));
4902     return;
4903   }
4904   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4905   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4906     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4907   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4908   {
4909     plci->Sig.RNR = 1;
4910     return;
4911   }
4912   if(plci->Sig.Ind==HANGUP && plci->channels)
4913   {
4914     plci->Sig.RNR = 1;
4915     plci->hangup_flow_ctrl_timer++;
4916     /* recover the network layer after timeout */
4917     if(plci->hangup_flow_ctrl_timer==100)
4918     {
4919       dbug(1,dprintf("Exceptional disc"));
4920       plci->Sig.RNR = 0;
4921       plci->hangup_flow_ctrl_timer = 0;
4922       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4923       {
4924         if (a->ncci_plci[ncci] == plci->Id)
4925         {
4926           cleanup_ncci_data (plci, ncci);
4927           if(plci->channels)plci->channels--;
4928           if (plci->appl)
4929             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4930         }
4931       }
4932       if (plci->appl)
4933         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4934       plci_remove(plci);
4935       plci->State=IDLE;
4936     }
4937     return;
4938   }
4939 
4940   /* do first parse the info with no OAD in, because OAD will be converted */
4941   /* first the multiple facility IE, then mult. progress ind.              */
4942   /* then the parameters for the info_ind + conn_ind                       */
4943   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4944   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4945   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4946 
4947   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4948 
4949   IndParse(plci,parms_id,parms,0);
4950   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4951   esc_chi  = parms[14];
4952   esc_law  = parms[18];
4953   pty_cai  = parms[24];
4954   esc_cr   = parms[25];
4955   esc_profile = parms[27];
4956   if(esc_cr[0] && plci)
4957   {
4958     if(plci->cr_enquiry && plci->appl)
4959     {
4960       plci->cr_enquiry = false;
4961       /* d = MANU_ID            */
4962       /* w = m_command          */
4963       /* b = total length       */
4964       /* b = indication type    */
4965       /* b = length of all IEs  */
4966       /* b = IE1                */
4967       /* S = IE1 length + cont. */
4968       /* b = IE2                */
4969       /* S = IE2 length + cont. */
4970       sendf(plci->appl,
4971         _MANUFACTURER_I,
4972         Id,
4973         0,
4974         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4975         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);
4976     }
4977   }
4978   /* create the additional info structure                                  */
4979   add_i[1] = parms[15]; /* KEY of additional info */
4980   add_i[2] = parms[11]; /* UUI of additional info */
4981   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4982 
4983   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4984   /* indication returns by the card if requested by the function           */
4985   /* AutomaticLaw() after driver init                                      */
4986   if (a->automatic_law<4)
4987   {
4988     if(esc_law[0]){
4989       if(esc_law[2]){
4990         dbug(0,dprintf("u-Law selected"));
4991         a->u_law = 1;
4992       }
4993       else {
4994         dbug(0,dprintf("a-Law selected"));
4995         a->u_law = 0;
4996       }
4997       a->automatic_law = 4;
4998       if(plci==a->automatic_lawPLCI) {
4999         plci->internal_command = 0;
5000         sig_req(plci,REMOVE,0);
5001         send_req(plci);
5002         a->automatic_lawPLCI = NULL;
5003       }
5004     }
5005     if (esc_profile[0])
5006     {
5007       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5008         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
5009         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
5010         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
5011 
5012       a->profile.Global_Options &= 0x000000ffL;
5013       a->profile.B1_Protocols &= 0x000003ffL;
5014       a->profile.B2_Protocols &= 0x00001fdfL;
5015       a->profile.B3_Protocols &= 0x000000b7L;
5016 
5017       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
5018         GL_BCHANNEL_OPERATION_SUPPORTED;
5019       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
5020       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
5021       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5022       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5023       a->man_profile.private_options = 0;
5024 
5025       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5026       {
5027         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5028         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5029       }
5030 
5031 
5032       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5033         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5034       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5035       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5036 
5037 
5038       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5039         a->man_profile.private_options |= 1L << PRIVATE_T38;
5040 
5041 
5042       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5043         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5044 
5045 
5046       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5047         a->man_profile.private_options |= 1L << PRIVATE_V18;
5048 
5049 
5050       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5051         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5052 
5053 
5054       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5055         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5056 
5057 
5058       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5059         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5060 
5061 
5062       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5063         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5064 
5065 
5066       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5067         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5068 
5069     }
5070     else
5071     {
5072       a->profile.Global_Options &= 0x0000007fL;
5073       a->profile.B1_Protocols &= 0x000003dfL;
5074       a->profile.B2_Protocols &= 0x00001adfL;
5075       a->profile.B3_Protocols &= 0x000000b7L;
5076       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5077     }
5078     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5079       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5080     {
5081       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5082     }
5083     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5084     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5085       UnMapController (a->Id), a->profile.Global_Options,
5086       a->profile.B1_Protocols, a->profile.B2_Protocols,
5087       a->profile.B3_Protocols, a->manufacturer_features));
5088   }
5089   /* codec plci for the handset/hook state support is just an internal id  */
5090   if(plci!=a->AdvCodecPLCI)
5091   {
5092     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5093     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5094     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5095     SendInfo(plci,Id, parms, force_mt_info);
5096 
5097     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5098 
5099   }
5100 
5101   /* switch the codec to the b-channel                                     */
5102   if(esc_chi[0] && plci && !plci->SuppState){
5103     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5104     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5105     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5106     if(plci->tel==ADV_VOICE && plci->appl) {
5107       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5108     }
5109   }
5110 
5111   if(plci->appl) Number = plci->appl->Number++;
5112 
5113   switch(plci->Sig.Ind) {
5114   /* Response to Get_Supported_Services request */
5115   case S_SUPPORTED:
5116     dbug(1,dprintf("S_Supported"));
5117     if(!plci->appl) break;
5118     if(pty_cai[0]==4)
5119     {
5120       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5121     }
5122     else
5123     {
5124       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5125     }
5126     PUT_WORD (&CF_Ind[1], 0);
5127     PUT_WORD (&CF_Ind[4], 0);
5128     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5129     plci_remove(plci);
5130     break;
5131                     
5132   /* Supplementary Service rejected */
5133   case S_SERVICE_REJ:
5134     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5135     if(!pty_cai[0]) break;
5136     switch (pty_cai[5])
5137     {
5138     case ECT_EXECUTE:
5139     case THREE_PTY_END:
5140     case THREE_PTY_BEGIN:
5141       if(!plci->relatedPTYPLCI) break;
5142       tplci = plci->relatedPTYPLCI;
5143       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5144       if(tplci->tel) rId|=EXT_CONTROLLER;
5145       if(pty_cai[5]==ECT_EXECUTE)
5146       {
5147         PUT_WORD(&SS_Ind[1],S_ECT);
5148 
5149         plci->vswitchstate=0;
5150         plci->relatedPTYPLCI->vswitchstate=0;
5151 
5152       }
5153       else
5154       {
5155         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5156       }
5157       if(pty_cai[2]!=0xff)
5158       {
5159         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5160       }
5161       else
5162       {
5163         PUT_WORD(&SS_Ind[4],0x300E);
5164       }
5165       plci->relatedPTYPLCI = NULL;
5166       plci->ptyState = 0;
5167       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5168       break;
5169 
5170     case CALL_DEFLECTION:
5171       if(pty_cai[2]!=0xff)
5172       {
5173         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5174       }
5175       else
5176       {
5177         PUT_WORD(&SS_Ind[4],0x300E);
5178       }
5179       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5180       for(i=0; i<max_appl; i++)
5181       {
5182         if(application[i].CDEnable)
5183         {
5184           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5185           application[i].CDEnable = false;
5186         }
5187       }
5188       break;
5189 
5190     case DEACTIVATION_DIVERSION:
5191     case ACTIVATION_DIVERSION:
5192     case DIVERSION_INTERROGATE_CFU:
5193     case DIVERSION_INTERROGATE_CFB:
5194     case DIVERSION_INTERROGATE_CFNR:
5195     case DIVERSION_INTERROGATE_NUM:
5196     case CCBS_REQUEST:
5197     case CCBS_DEACTIVATE:
5198     case CCBS_INTERROGATE:
5199       if(!plci->appl) break;
5200       if(pty_cai[2]!=0xff)
5201       {
5202         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5203       }
5204       else
5205       {
5206         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5207       }
5208       switch (pty_cai[5])
5209       {
5210         case DEACTIVATION_DIVERSION:
5211           dbug(1,dprintf("Deact_Div"));
5212           Interr_Err_Ind[0]=0x9;
5213           Interr_Err_Ind[3]=0x6;
5214           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5215           break;
5216         case ACTIVATION_DIVERSION:
5217           dbug(1,dprintf("Act_Div"));
5218           Interr_Err_Ind[0]=0x9;
5219           Interr_Err_Ind[3]=0x6;
5220           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5221           break;
5222         case DIVERSION_INTERROGATE_CFU:
5223         case DIVERSION_INTERROGATE_CFB:
5224         case DIVERSION_INTERROGATE_CFNR:
5225           dbug(1,dprintf("Interr_Div"));
5226           Interr_Err_Ind[0]=0xa;
5227           Interr_Err_Ind[3]=0x7;
5228           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5229           break;
5230         case DIVERSION_INTERROGATE_NUM:
5231           dbug(1,dprintf("Interr_Num"));
5232           Interr_Err_Ind[0]=0xa;
5233           Interr_Err_Ind[3]=0x7;
5234           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5235           break;
5236         case CCBS_REQUEST:
5237           dbug(1,dprintf("CCBS Request"));
5238           Interr_Err_Ind[0]=0xd;
5239           Interr_Err_Ind[3]=0xa;
5240           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5241           break;
5242         case CCBS_DEACTIVATE:
5243           dbug(1,dprintf("CCBS Deactivate"));
5244           Interr_Err_Ind[0]=0x9;
5245           Interr_Err_Ind[3]=0x6;
5246           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5247           break;
5248         case CCBS_INTERROGATE:
5249           dbug(1,dprintf("CCBS Interrogate"));
5250           Interr_Err_Ind[0]=0xb;
5251           Interr_Err_Ind[3]=0x8;
5252           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5253           break;
5254       }
5255       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5256       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5257       plci_remove(plci);
5258       break;
5259     case ACTIVATION_MWI:      
5260     case DEACTIVATION_MWI:
5261       if(pty_cai[5]==ACTIVATION_MWI)
5262       {
5263         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5264       }
5265       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5266       
5267       if(pty_cai[2]!=0xff)
5268       {
5269         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5270       }
5271       else
5272       {
5273         PUT_WORD(&SS_Ind[4],0x300E);
5274       }
5275 
5276       if(plci->cr_enquiry)
5277       {
5278         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5279         plci_remove(plci);
5280       }
5281       else
5282       {
5283         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5284       }
5285       break;
5286     case CONF_ADD: /* ERROR */
5287     case CONF_BEGIN:
5288     case CONF_DROP:
5289     case CONF_ISOLATE:
5290     case CONF_REATTACH:
5291       CONF_Ind[0]=9;
5292       CONF_Ind[3]=6;   
5293       switch(pty_cai[5])
5294       {
5295       case CONF_BEGIN:
5296           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5297           plci->ptyState = 0;
5298           break;
5299       case CONF_DROP:
5300           CONF_Ind[0]=5;
5301           CONF_Ind[3]=2;
5302           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5303           plci->ptyState = CONNECTED;
5304           break;
5305       case CONF_ISOLATE:
5306           CONF_Ind[0]=5;
5307           CONF_Ind[3]=2;
5308           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5309           plci->ptyState = CONNECTED;
5310           break;
5311       case CONF_REATTACH:
5312           CONF_Ind[0]=5;
5313           CONF_Ind[3]=2;
5314           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5315           plci->ptyState = CONNECTED;
5316           break;
5317       case CONF_ADD:
5318           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5319           plci->relatedPTYPLCI = NULL;
5320           tplci=plci->relatedPTYPLCI;
5321           if(tplci) tplci->ptyState = CONNECTED;
5322           plci->ptyState = CONNECTED;
5323           break;
5324       }
5325           
5326       if(pty_cai[2]!=0xff)
5327       {
5328         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5329       }
5330       else
5331       {
5332         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5333                                             within the required time */
5334       }
5335 
5336       PUT_DWORD(&CONF_Ind[6],0x0);
5337       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5338       break;
5339     }
5340     break;
5341 
5342   /* Supplementary Service indicates success */
5343   case S_SERVICE:
5344     dbug(1,dprintf("Service_Ind"));
5345     PUT_WORD (&CF_Ind[4], 0);
5346     switch (pty_cai[5])
5347     {
5348     case THREE_PTY_END:
5349     case THREE_PTY_BEGIN:
5350     case ECT_EXECUTE:
5351       if(!plci->relatedPTYPLCI) break;
5352       tplci = plci->relatedPTYPLCI;
5353       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5354       if(tplci->tel) rId|=EXT_CONTROLLER;
5355       if(pty_cai[5]==ECT_EXECUTE)
5356       {
5357         PUT_WORD(&SS_Ind[1],S_ECT);
5358 
5359         if(plci->vswitchstate!=3)
5360         {
5361 
5362         plci->ptyState = IDLE;
5363         plci->relatedPTYPLCI = NULL;
5364         plci->ptyState = 0;
5365 
5366         }
5367 
5368         dbug(1,dprintf("ECT OK"));
5369         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5370 
5371 
5372 
5373       }
5374       else
5375       {
5376         switch (plci->ptyState)
5377         {
5378         case S_3PTY_BEGIN:
5379           plci->ptyState = CONNECTED;
5380           dbug(1,dprintf("3PTY ON"));
5381           break;
5382 
5383         case S_3PTY_END:
5384           plci->ptyState = IDLE;
5385           plci->relatedPTYPLCI = NULL;
5386           plci->ptyState = 0;
5387           dbug(1,dprintf("3PTY OFF"));
5388           break;
5389         }
5390         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5391         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5392       }
5393       break;
5394 
5395     case CALL_DEFLECTION:
5396       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5397       for(i=0; i<max_appl; i++)
5398       {
5399         if(application[i].CDEnable)
5400         {
5401           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5402           application[i].CDEnable = false;
5403         }
5404       }
5405       break;
5406 
5407     case DEACTIVATION_DIVERSION:
5408     case ACTIVATION_DIVERSION:
5409       if(!plci->appl) break;
5410       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5411       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5412       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5413       plci_remove(plci);
5414       break;
5415 
5416     case DIVERSION_INTERROGATE_CFU:
5417     case DIVERSION_INTERROGATE_CFB:
5418     case DIVERSION_INTERROGATE_CFNR:
5419     case DIVERSION_INTERROGATE_NUM:
5420     case CCBS_REQUEST:
5421     case CCBS_DEACTIVATE:
5422     case CCBS_INTERROGATE:
5423       if(!plci->appl) break;
5424       switch (pty_cai[5])
5425       {
5426         case DIVERSION_INTERROGATE_CFU:
5427         case DIVERSION_INTERROGATE_CFB:
5428         case DIVERSION_INTERROGATE_CFNR:
5429           dbug(1,dprintf("Interr_Div"));
5430           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5431           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5432           break;
5433         case DIVERSION_INTERROGATE_NUM:
5434           dbug(1,dprintf("Interr_Num"));
5435           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5436           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5437           break;
5438         case CCBS_REQUEST:
5439           dbug(1,dprintf("CCBS Request"));
5440           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5441           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5442           break;
5443         case CCBS_DEACTIVATE:
5444           dbug(1,dprintf("CCBS Deactivate"));
5445           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5446           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5447           break;
5448         case CCBS_INTERROGATE:
5449           dbug(1,dprintf("CCBS Interrogate"));
5450           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5451           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5452           break;
5453       }
5454       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5455       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5456       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5457       plci_remove(plci);
5458       break;
5459 
5460     case ACTIVATION_MWI:
5461     case DEACTIVATION_MWI:
5462       if(pty_cai[5]==ACTIVATION_MWI)
5463       {
5464         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5465       }
5466       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5467       if(plci->cr_enquiry)
5468       {
5469         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5470         plci_remove(plci);
5471       }
5472       else
5473       {
5474         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5475       }
5476       break;
5477     case MWI_INDICATION:
5478       if(pty_cai[0]>=0x12)
5479       {
5480         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5481         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5482         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5483         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5484         {
5485           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5486           {
5487             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5488             plci_remove(plci);
5489             return;
5490           }
5491           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5492           pty_cai[0]=0;
5493         }
5494         else
5495         {
5496           for(i=0; i<max_appl; i++)
5497           {                     
5498             if(a->Notification_Mask[i]&SMASK_MWI)
5499             {
5500               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5501               pty_cai[0]=0;
5502             }
5503           }
5504         }
5505 
5506         if(!pty_cai[0])
5507         { /* acknowledge */
5508           facility[2]= 0; /* returncode */
5509         }
5510         else facility[2]= 0xff;
5511       }
5512       else
5513       {
5514         /* reject */
5515         facility[2]= 0xff; /* returncode */
5516       }
5517       facility[0]= 2;
5518       facility[1]= MWI_RESPONSE; /* Function */
5519       add_p(plci,CAI,facility);
5520       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5521       sig_req(plci,S_SERVICE,0);
5522       send_req(plci);
5523       plci->command = 0;
5524       next_internal_command (Id, plci);
5525       break;
5526     case CONF_ADD: /* OK */
5527     case CONF_BEGIN:
5528     case CONF_DROP:
5529     case CONF_ISOLATE:
5530     case CONF_REATTACH:
5531     case CONF_PARTYDISC:
5532       CONF_Ind[0]=9;
5533       CONF_Ind[3]=6;
5534       switch(pty_cai[5])
5535       {
5536       case CONF_BEGIN:
5537           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5538           if(pty_cai[0]==6)
5539           {
5540               d=pty_cai[6];
5541               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5542           }
5543           else
5544           {
5545               PUT_DWORD(&CONF_Ind[6],0x0);
5546           }
5547           break;
5548       case CONF_ISOLATE:
5549           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5550           CONF_Ind[0]=5;
5551           CONF_Ind[3]=2;
5552           break;
5553       case CONF_REATTACH:
5554           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5555           CONF_Ind[0]=5;
5556           CONF_Ind[3]=2;
5557           break;
5558       case CONF_DROP:
5559           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5560           CONF_Ind[0]=5;
5561           CONF_Ind[3]=2;
5562           break;
5563       case CONF_ADD:
5564           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5565           d=pty_cai[6];
5566           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5567           tplci=plci->relatedPTYPLCI;
5568           if(tplci) tplci->ptyState = CONNECTED;
5569           break;
5570       case CONF_PARTYDISC:
5571           CONF_Ind[0]=7;
5572           CONF_Ind[3]=4;          
5573           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5574           d=pty_cai[6];
5575           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5576           break;
5577       }
5578       plci->ptyState = CONNECTED;
5579       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5580       break;
5581     case CCBS_INFO_RETAIN:
5582     case CCBS_ERASECALLLINKAGEID:
5583     case CCBS_STOP_ALERTING:
5584       CONF_Ind[0]=5;
5585       CONF_Ind[3]=2;
5586       switch(pty_cai[5])
5587       {
5588       case CCBS_INFO_RETAIN:
5589         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5590         break;
5591       case CCBS_STOP_ALERTING:
5592         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5593     break;
5594       case CCBS_ERASECALLLINKAGEID:
5595         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5596         CONF_Ind[0]=7;
5597         CONF_Ind[3]=4;
5598         CONF_Ind[6]=0;
5599         CONF_Ind[7]=0;
5600         break;
5601       }      
5602       w=pty_cai[6];
5603       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5604 
5605       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5606       {
5607         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5608       }
5609       else
5610       {
5611         for(i=0; i<max_appl; i++)
5612             if(a->Notification_Mask[i]&SMASK_CCBS)
5613                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5614       }
5615       break;
5616     }
5617     break;
5618   case CALL_HOLD_REJ:
5619     cau = parms[7];
5620     if(cau)
5621     {
5622       i = _L3_CAUSE | cau[2];
5623       if(cau[2]==0) i = 0x3603;
5624     }
5625     else
5626     {
5627       i = 0x3603;
5628     }
5629     PUT_WORD(&SS_Ind[1],S_HOLD);
5630     PUT_WORD(&SS_Ind[4],i);
5631     if(plci->SuppState == HOLD_REQUEST)
5632     {
5633       plci->SuppState = IDLE;
5634       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5635     }
5636     break;
5637 
5638   case CALL_HOLD_ACK:
5639     if(plci->SuppState == HOLD_REQUEST)
5640     {
5641       plci->SuppState = CALL_HELD;
5642       CodecIdCheck(a, plci);
5643       start_internal_command (Id, plci, hold_save_command);
5644     }
5645     break;
5646 
5647   case CALL_RETRIEVE_REJ:
5648     cau = parms[7];
5649     if(cau)
5650     {
5651       i = _L3_CAUSE | cau[2];
5652       if(cau[2]==0) i = 0x3603;
5653     }
5654     else
5655     {
5656       i = 0x3603;
5657     }
5658     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5659     PUT_WORD(&SS_Ind[4],i);
5660     if(plci->SuppState == RETRIEVE_REQUEST)
5661     {
5662       plci->SuppState = CALL_HELD;
5663       CodecIdCheck(a, plci);
5664       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5665     }
5666     break;
5667 
5668   case CALL_RETRIEVE_ACK:
5669     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5670     if(plci->SuppState == RETRIEVE_REQUEST)
5671     {
5672       plci->SuppState = IDLE;
5673       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5674       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5675       if(plci->tel)
5676       {
5677         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5678         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5679         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5680         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5681         {
5682           dbug(1,dprintf("Get B-ch"));
5683           start_internal_command (Id, plci, retrieve_restore_command);
5684         }
5685         else
5686           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5687       }
5688       else
5689         start_internal_command (Id, plci, retrieve_restore_command);
5690     }
5691     break;
5692 
5693   case INDICATE_IND:
5694     if(plci->State != LISTENING) {
5695       sig_req(plci,HANGUP,0);
5696       send_req(plci);
5697       break;
5698     }
5699     cip = find_cip(a,parms[4],parms[6]);
5700     cip_mask = 1L<<cip;
5701     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5702     clear_c_ind_mask (plci);
5703     if (!remove_started && !a->adapter_disabled)
5704     {
5705       set_c_ind_mask_bit (plci, MAX_APPL);
5706       group_optimization(a, plci);
5707       for(i=0; i<max_appl; i++) {
5708         if(application[i].Id
5709         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5710         && CPN_filter_ok(parms[0],a,i)
5711         && test_group_ind_mask_bit (plci, i) ) {
5712           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5713           set_c_ind_mask_bit (plci, i);
5714           dump_c_ind_mask (plci);
5715           plci->State = INC_CON_PENDING;
5716           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5717             CALL_DIR_IN | CALL_DIR_ANSWER;
5718           if(esc_chi[0]) {
5719             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5720             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5721           }
5722           /* if a listen on the ext controller is done, check if hook states */
5723           /* are supported or if just a on board codec must be activated     */
5724           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5725             if(a->profile.Global_Options & HANDSET)
5726               plci->tel = ADV_VOICE;
5727             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5728               plci->tel = CODEC;
5729             if(plci->tel) Id|=EXT_CONTROLLER;
5730             a->codec_listen[i] = plci;
5731           }
5732 
5733           sendf(&application[i],_CONNECT_I,Id,0,
5734                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5735                              parms[0],    /* CalledPartyNumber   */
5736                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5737                              parms[2],    /* CalledPartySubad    */
5738                              parms[3],    /* CallingPartySubad   */
5739                              parms[4],    /* BearerCapability    */
5740                              parms[5],    /* LowLC               */
5741                              parms[6],    /* HighLC              */
5742                              ai_len,      /* nested struct add_i */
5743                              add_i[0],    /* B channel info    */
5744                              add_i[1],    /* keypad facility   */
5745                              add_i[2],    /* user user data    */
5746                              add_i[3],    /* nested facility   */
5747                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5748                              );
5749           SendSSExtInd(&application[i],
5750                         plci,
5751                         Id,
5752                         multi_ssext_parms);
5753           SendSetupInfo(&application[i],
5754                         plci,
5755                         Id,
5756                         parms,
5757                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5758         }
5759       }
5760       clear_c_ind_mask_bit (plci, MAX_APPL);
5761       dump_c_ind_mask (plci);
5762     }
5763     if(c_ind_mask_empty (plci)) {
5764       sig_req(plci,HANGUP,0);
5765       send_req(plci);
5766       plci->State = IDLE;
5767     }
5768     plci->notifiedcall = 0;
5769     a->listen_active--;
5770     listen_check(a);
5771     break;
5772 
5773   case CALL_PEND_NOTIFY:
5774     plci->notifiedcall = 1;
5775     listen_check(a);
5776     break;
5777 
5778   case CALL_IND:
5779   case CALL_CON:
5780     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5781     {
5782       if(plci->internal_command==PERM_COD_CONN_PEND)
5783       {
5784         if(plci->State==ADVANCED_VOICE_NOSIG)
5785         {
5786           dbug(1,dprintf("***Codec OK"));
5787           if(a->AdvSignalPLCI)
5788           {
5789             tplci = a->AdvSignalPLCI;
5790             if(tplci->spoofed_msg)
5791             {
5792               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5793               tplci->command = 0;
5794               tplci->internal_command = 0;
5795               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5796               switch (tplci->spoofed_msg)
5797               {
5798               case CALL_RES:
5799                 tplci->command = _CONNECT_I|RESPONSE;
5800                 api_load_msg (&tplci->saved_msg, saved_parms);
5801                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5802                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5803                 {
5804                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5805                   add_p(tplci,LLI,"\x01\x01");
5806                 }
5807                 add_s(tplci, CONN_NR, &saved_parms[2]);
5808                 add_s(tplci, LLC, &saved_parms[4]);
5809                 add_ai(tplci, &saved_parms[5]);
5810                 tplci->State = INC_CON_ACCEPT;
5811                 sig_req(tplci, CALL_RES,0);
5812                 send_req(tplci);
5813                 break;
5814 
5815               case AWAITING_SELECT_B:
5816                 dbug(1,dprintf("Select_B continue"));
5817                 start_internal_command (x_Id, tplci, select_b_command);
5818                 break;
5819 
5820               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5821                 if(!tplci->Sig.Id)
5822                 {
5823                   dbug(1,dprintf("No SigID!"));
5824                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5825                   plci_remove(tplci);
5826                   break;
5827                 }
5828                 tplci->command = _MANUFACTURER_R;
5829                 api_load_msg (&tplci->saved_msg, saved_parms);
5830                 dir = saved_parms[2].info[0];
5831                 if(dir==1) {
5832                   sig_req(tplci,CALL_REQ,0);
5833                 }
5834                 else if(!dir){
5835                   sig_req(tplci,LISTEN_REQ,0);
5836                 }
5837                 send_req(tplci);
5838                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5839                 break;
5840 
5841               case (CALL_REQ|AWAITING_MANUF_CON):
5842                 sig_req(tplci,CALL_REQ,0);
5843                 send_req(tplci);
5844                 break;
5845 
5846               case CALL_REQ:
5847                 if(!tplci->Sig.Id)
5848                 {
5849                   dbug(1,dprintf("No SigID!"));
5850                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5851                   plci_remove(tplci);
5852                   break;
5853                 }
5854                 tplci->command = _CONNECT_R;
5855                 api_load_msg (&tplci->saved_msg, saved_parms);
5856                 add_s(tplci,CPN,&saved_parms[1]);
5857                 add_s(tplci,DSA,&saved_parms[3]);
5858                 add_ai(tplci,&saved_parms[9]);
5859                 sig_req(tplci,CALL_REQ,0);
5860                 send_req(tplci);
5861                 break;
5862 
5863               case CALL_RETRIEVE:
5864                 tplci->command = C_RETRIEVE_REQ;
5865                 sig_req(tplci,CALL_RETRIEVE,0);
5866                 send_req(tplci);
5867                 break;
5868               }
5869               tplci->spoofed_msg = 0;
5870               if (tplci->internal_command == 0)
5871                 next_internal_command (x_Id, tplci);
5872             }
5873           }
5874           next_internal_command (Id, plci);
5875           break;
5876         }
5877         dbug(1,dprintf("***Codec Hook Init Req"));
5878         plci->internal_command = PERM_COD_HOOK;
5879         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5880         sig_req(plci,TEL_CTRL,0);
5881         send_req(plci);
5882       }
5883     }
5884     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5885     && plci->State!=INC_ACT_PENDING)
5886     {
5887       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5888       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5889       {
5890         chi[2] = plci->b_channel;
5891         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5892       }
5893       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5894       plci->State = INC_ACT_PENDING;
5895     }
5896     break;
5897 
5898   case TEL_CTRL:
5899     Number = 0;
5900     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5901     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5902       switch (ie[1]&0x91) {
5903         case 0x80:   /* hook off */
5904         case 0x81:
5905           if(plci->internal_command==PERM_COD_HOOK)
5906           {
5907             dbug(1,dprintf("init:hook_off"));
5908             plci->hook_state = ie[1];
5909             next_internal_command (Id, plci);
5910             break;
5911           }
5912           else /* ignore doubled hook indications */
5913           {
5914             if( ((plci->hook_state)&0xf0)==0x80)
5915             {
5916               dbug(1,dprintf("ignore hook"));
5917               break;
5918             }
5919             plci->hook_state = ie[1]&0x91;
5920           }
5921           /* check for incoming call pending */
5922           /* and signal '+'.Appl must decide */
5923           /* with connect_res if call must   */
5924           /* accepted or not                 */
5925           for(i=0, tplci=NULL;i<max_appl;i++){
5926             if(a->codec_listen[i]
5927             && (a->codec_listen[i]->State==INC_CON_PENDING
5928               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5929               tplci = a->codec_listen[i];
5930               tplci->appl = &application[i];
5931             }
5932           }
5933           /* no incoming call, do outgoing call */
5934           /* and signal '+' if outg. setup   */
5935           if(!a->AdvSignalPLCI && !tplci){
5936             if((i=get_plci(a))) {
5937               a->AdvSignalPLCI = &a->plci[i-1];
5938               tplci = a->AdvSignalPLCI;
5939               tplci->tel  = ADV_VOICE;
5940               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5941               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5942                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5943                 add_p(tplci,LLI,"\x01\x01");
5944               }
5945               add_p(tplci, CAI, voice_cai);
5946               add_p(tplci, OAD, a->TelOAD);
5947               add_p(tplci, OSA, a->TelOSA);
5948               add_p(tplci,SHIFT|6,NULL);
5949               add_p(tplci,SIN,"\x02\x01\x00");
5950               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5951               sig_req(tplci,ASSIGN,DSIG_ID);
5952               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5953               a->AdvSignalPLCI->command = 0;
5954               tplci->appl = a->AdvSignalAppl;
5955               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5956               send_req(tplci);
5957             }
5958 
5959           }
5960 
5961           if(!tplci) break;
5962           Id = ((word)tplci->Id<<8)|a->Id;
5963           Id|=EXT_CONTROLLER;
5964           sendf(tplci->appl,
5965                 _FACILITY_I,
5966                 Id,
5967                 0,
5968                 "ws", (word)0, "\x01+");
5969           break;
5970 
5971         case 0x90:   /* hook on  */
5972         case 0x91:
5973           if(plci->internal_command==PERM_COD_HOOK)
5974           {
5975             dbug(1,dprintf("init:hook_on"));
5976             plci->hook_state = ie[1]&0x91;
5977             next_internal_command (Id, plci);
5978             break;
5979           }
5980           else /* ignore doubled hook indications */
5981           {
5982             if( ((plci->hook_state)&0xf0)==0x90) break;
5983             plci->hook_state = ie[1]&0x91;
5984           }
5985           /* hangup the adv. voice call and signal '-' to the appl */
5986           if(a->AdvSignalPLCI) {
5987             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5988             if(plci->tel) Id|=EXT_CONTROLLER;
5989             sendf(a->AdvSignalAppl,
5990                   _FACILITY_I,
5991                   Id,
5992                   0,
5993                   "ws", (word)0, "\x01-");
5994             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5995             a->AdvSignalPLCI->command = 0;
5996             sig_req(a->AdvSignalPLCI,HANGUP,0);
5997             send_req(a->AdvSignalPLCI);
5998           }
5999           break;
6000       }
6001     }
6002     break;
6003 
6004   case RESUME:
6005     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
6006     PUT_WORD(&resume_cau[4],GOOD);
6007     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6008     break;
6009 
6010   case SUSPEND:
6011     clear_c_ind_mask (plci);
6012 
6013     if (plci->NL.Id && !plci->nl_remove_id) {
6014       mixer_remove (plci);
6015       nl_req_ncci(plci,REMOVE,0);
6016     }
6017     if (!plci->sig_remove_id) {
6018       plci->internal_command = 0;
6019       sig_req(plci,REMOVE,0);
6020     }
6021     send_req(plci);
6022     if(!plci->channels) {
6023       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6024       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6025     }
6026     break;
6027 
6028   case SUSPEND_REJ:
6029     break;
6030 
6031   case HANGUP:
6032     plci->hangup_flow_ctrl_timer=0;
6033     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6034     cau = parms[7];
6035     if(cau) {
6036       i = _L3_CAUSE | cau[2];
6037       if(cau[2]==0) i = 0;
6038       else if(cau[2]==8) i = _L1_ERROR;
6039       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6040       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6041     }
6042     else {
6043       i = _L3_ERROR;
6044     }
6045 
6046     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6047     {
6048       for(i=0; i<max_appl; i++)
6049       {
6050         if(test_c_ind_mask_bit (plci, i))
6051           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6052       }
6053     }
6054     else
6055     {
6056       clear_c_ind_mask (plci);
6057     }
6058     if(!plci->appl)
6059     {
6060       if (plci->State == LISTENING)
6061       {
6062         plci->notifiedcall=0;
6063         a->listen_active--;
6064       }
6065       plci->State = INC_DIS_PENDING;
6066       if(c_ind_mask_empty (plci))
6067       {
6068         plci->State = IDLE;
6069         if (plci->NL.Id && !plci->nl_remove_id)
6070         {
6071           mixer_remove (plci);
6072           nl_req_ncci(plci,REMOVE,0);
6073         }
6074         if (!plci->sig_remove_id)
6075         {
6076           plci->internal_command = 0;
6077           sig_req(plci,REMOVE,0);
6078         }
6079         send_req(plci);
6080       }
6081     }
6082     else
6083     {
6084         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6085         /* result in a second HANGUP! Don't generate another        */
6086         /* DISCONNECT                                               */
6087       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6088       {
6089         if(plci->State==RESUMING)
6090         {
6091           PUT_WORD(&resume_cau[4],i);
6092           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6093         }
6094         plci->State = INC_DIS_PENDING;
6095         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6096       }
6097     }
6098     break;
6099 
6100   case SSEXT_IND:
6101     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6102     break;
6103 
6104   case VSWITCH_REQ:
6105     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6106     break;
6107   case VSWITCH_IND:
6108  if(plci->relatedPTYPLCI &&
6109   plci->vswitchstate==3 &&
6110   plci->relatedPTYPLCI->vswitchstate==3 &&
6111   parms[MAXPARMSIDS-1][0])
6112  {
6113   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6114   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6115   send_req(plci->relatedPTYPLCI);
6116  }
6117     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6118     break;
6119 
6120   }
6121 }
6122 
6123 
6124 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6125 {
6126   word i;
6127   byte   * ie;
6128   word Info_Number;
6129   byte   * Info_Element;
6130   word Info_Mask = 0;
6131 
6132   dbug(1,dprintf("SetupInfo"));
6133 
6134   for(i=0; i<MAXPARMSIDS; i++) {
6135     ie = parms[i];
6136     Info_Number = 0;
6137     Info_Element = ie;
6138     if(ie[0]) {
6139       switch(i) {
6140       case 0:
6141         dbug(1,dprintf("CPN "));
6142         Info_Number = 0x0070;
6143         Info_Mask   = 0x80;
6144         Info_Sent_Flag = true;
6145         break;
6146       case 8:  /* display      */
6147         dbug(1,dprintf("display(%d)",i));
6148         Info_Number = 0x0028;
6149         Info_Mask = 0x04;
6150         Info_Sent_Flag = true;
6151         break;
6152       case 16: /* Channel Id */
6153         dbug(1,dprintf("CHI"));
6154         Info_Number = 0x0018;
6155         Info_Mask = 0x100;
6156         Info_Sent_Flag = true;
6157         mixer_set_bchannel_id (plci, Info_Element);
6158         break;
6159       case 19: /* Redirected Number */
6160         dbug(1,dprintf("RDN"));
6161         Info_Number = 0x0074;
6162         Info_Mask = 0x400;
6163         Info_Sent_Flag = true;
6164         break;
6165       case 20: /* Redirected Number extended */
6166         dbug(1,dprintf("RDX"));
6167         Info_Number = 0x0073;
6168         Info_Mask = 0x400;
6169         Info_Sent_Flag = true;
6170         break;
6171       case 22: /* Redirecing Number  */
6172         dbug(1,dprintf("RIN"));
6173         Info_Number = 0x0076;
6174         Info_Mask = 0x400;
6175         Info_Sent_Flag = true;
6176         break;
6177       default:
6178         Info_Number = 0;
6179         break;
6180       }
6181     }
6182 
6183     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6184       Info_Number = 0x8000 |5;
6185       Info_Mask = 0x10;
6186       Info_Element = "";
6187     }
6188 
6189     if(Info_Sent_Flag && Info_Number){
6190       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6191         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6192       }
6193     }
6194   }
6195 }
6196 
6197 
6198 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6199 {
6200   word i;
6201   word j;
6202   word k;
6203   byte   * ie;
6204   word Info_Number;
6205   byte   * Info_Element;
6206   word Info_Mask = 0;
6207   static byte charges[5] = {4,0,0,0,0};
6208   static byte cause[] = {0x02,0x80,0x00};
6209   APPL   *appl;
6210 
6211   dbug(1,dprintf("InfoParse "));
6212 
6213   if(
6214         !plci->appl
6215         && !plci->State
6216         && plci->Sig.Ind!=NCR_FACILITY
6217       )
6218   {
6219     dbug(1,dprintf("NoParse "));
6220     return;
6221   }
6222   cause[2] = 0;
6223   for(i=0; i<MAXPARMSIDS; i++) {
6224     ie = parms[i];
6225     Info_Number = 0;
6226     Info_Element = ie;
6227     if(ie[0]) {
6228       switch(i) {
6229       case 0:
6230         dbug(1,dprintf("CPN "));
6231         Info_Number = 0x0070;
6232         Info_Mask   = 0x80;
6233         break;
6234       case 7: /* ESC_CAU */
6235         dbug(1,dprintf("cau(0x%x)",ie[2]));
6236         Info_Number = 0x0008;
6237         Info_Mask = 0x00;
6238         cause[2] = ie[2];
6239         Info_Element = NULL;
6240         break;
6241       case 8:  /* display      */
6242         dbug(1,dprintf("display(%d)",i));
6243         Info_Number = 0x0028;
6244         Info_Mask = 0x04;
6245         break;
6246       case 9:  /* Date display */
6247         dbug(1,dprintf("date(%d)",i));
6248         Info_Number = 0x0029;
6249         Info_Mask = 0x02;
6250         break;
6251       case 10: /* charges */
6252         for(j=0;j<4;j++) charges[1+j] = 0;
6253         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6254         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6255         Info_Number = 0x4000;
6256         Info_Mask = 0x40;
6257         Info_Element = charges;
6258         break;
6259       case 11: /* user user info */
6260         dbug(1,dprintf("uui"));
6261         Info_Number = 0x007E;
6262         Info_Mask = 0x08;
6263         break;
6264       case 12: /* congestion receiver ready */
6265         dbug(1,dprintf("clRDY"));
6266         Info_Number = 0x00B0;
6267         Info_Mask = 0x08;
6268         Info_Element = "";
6269         break;
6270       case 13: /* congestion receiver not ready */
6271         dbug(1,dprintf("clNRDY"));
6272         Info_Number = 0x00BF;
6273         Info_Mask = 0x08;
6274         Info_Element = "";
6275         break;
6276       case 15: /* Keypad Facility */
6277         dbug(1,dprintf("KEY"));
6278         Info_Number = 0x002C;
6279         Info_Mask = 0x20;
6280         break;
6281       case 16: /* Channel Id */
6282         dbug(1,dprintf("CHI"));
6283         Info_Number = 0x0018;
6284         Info_Mask = 0x100;
6285         mixer_set_bchannel_id (plci, Info_Element);
6286         break;
6287       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6288         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6289         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6290         Info_Number = 0x0008;
6291         Info_Mask = 0x01;
6292         if(cause[2] != ie[2]) Info_Element = cause;
6293         break;
6294       case 19: /* Redirected Number */
6295         dbug(1,dprintf("RDN"));
6296         Info_Number = 0x0074;
6297         Info_Mask = 0x400;
6298         break;
6299       case 22: /* Redirecing Number  */
6300         dbug(1,dprintf("RIN"));
6301         Info_Number = 0x0076;
6302         Info_Mask = 0x400;
6303         break;
6304       case 23: /* Notification Indicator  */
6305         dbug(1,dprintf("NI"));
6306         Info_Number = (word)NI;
6307         Info_Mask = 0x210;
6308         break;
6309       case 26: /* Call State  */
6310         dbug(1,dprintf("CST"));
6311         Info_Number = (word)CST;
6312         Info_Mask = 0x01; /* do with cause i.e. for now */
6313         break;
6314       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6315         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6316         Info_Number = 0x8000 |ie[3];
6317         if(iesent) Info_Mask = 0xffff;
6318         else  Info_Mask = 0x10;
6319         Info_Element = "";
6320         break;
6321       default:
6322         Info_Number  = 0;
6323         Info_Mask    = 0;
6324         Info_Element = "";
6325         break;
6326       }
6327     }
6328 
6329     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6330     {
6331       for(j=0; j<max_appl; j++)
6332       {
6333         appl = &application[j];
6334         if(Info_Number
6335         && appl->Id
6336         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6337         {
6338           dbug(1,dprintf("NCR_Ind"));
6339           iesent=true;
6340           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6341         }
6342       }
6343     }
6344     else if(!plci->appl)
6345     { /* overlap receiving broadcast */
6346       if(Info_Number==CPN
6347       || Info_Number==KEY
6348       || Info_Number==NI
6349       || Info_Number==DSP
6350       || Info_Number==UUI )
6351       {
6352         for(j=0; j<max_appl; j++)
6353         {
6354           if(test_c_ind_mask_bit (plci, j))
6355           {
6356             dbug(1,dprintf("Ovl_Ind"));
6357             iesent=true;
6358             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6359           }
6360         }
6361       }
6362     }               /* all other signalling states */
6363     else if(Info_Number
6364     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6365     {
6366       dbug(1,dprintf("Std_Ind"));
6367       iesent=true;
6368       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6369     }
6370   }
6371 }
6372 
6373 
6374 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6375                         dword info_mask, byte setupParse)
6376 {
6377   word i;
6378   word j;
6379   byte   * ie;
6380   word Info_Number;
6381   byte   * Info_Element;
6382   APPL   *appl;
6383   word Info_Mask = 0;
6384   byte iesent=0;
6385 
6386   if(
6387       !plci->appl
6388       && !plci->State
6389       && plci->Sig.Ind!=NCR_FACILITY
6390       && !setupParse
6391       )
6392   {
6393     dbug(1,dprintf("NoM-IEParse "));
6394     return 0;
6395   }
6396   dbug(1,dprintf("M-IEParse "));
6397 
6398   for(i=0; i<MAX_MULTI_IE; i++)
6399   {
6400     ie = parms[i];
6401     Info_Number = 0;
6402     Info_Element = ie;
6403     if(ie[0])
6404     {
6405       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6406       Info_Number = (word)ie_type;
6407       Info_Mask = (word)info_mask;
6408     }
6409 
6410     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6411     {
6412       for(j=0; j<max_appl; j++)
6413       {
6414         appl = &application[j];
6415         if(Info_Number
6416         && appl->Id
6417         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6418         {
6419           iesent = true;
6420           dbug(1,dprintf("Mlt_NCR_Ind"));
6421           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6422         }
6423       }
6424     }
6425     else if(!plci->appl && Info_Number)
6426     {                                        /* overlap receiving broadcast */
6427       for(j=0; j<max_appl; j++)
6428       {
6429         if(test_c_ind_mask_bit (plci, j))
6430         {
6431           iesent = true;
6432           dbug(1,dprintf("Mlt_Ovl_Ind"));
6433           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6434         }
6435       }
6436     }                                        /* all other signalling states */
6437     else if(Info_Number
6438     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6439     {
6440       iesent = true;
6441       dbug(1,dprintf("Mlt_Std_Ind"));
6442       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6443     }
6444   }
6445   return iesent;
6446 }
6447 
6448 static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6449 {
6450   word i;
6451    /* Format of multi_ssext_parms[i][]:
6452    0 byte length
6453    1 byte SSEXTIE
6454    2 byte SSEXT_REQ/SSEXT_IND
6455    3 byte length
6456    4 word SSExtCommand
6457    6... Params
6458    */
6459   if(
6460    plci
6461    && plci->State
6462    && plci->Sig.Ind!=NCR_FACILITY
6463     )
6464  for(i=0;i<MAX_MULTI_IE;i++)
6465     {
6466       if(parms[i][0]<6) continue;
6467    if(parms[i][2]==SSEXT_REQ) continue;
6468 
6469    if(appl)
6470    {
6471     parms[i][0]=0; /* kill it */
6472     sendf(appl,_MANUFACTURER_I,
6473     Id,
6474     0,
6475     "dwS",
6476     _DI_MANU_ID,
6477     _DI_SSEXT_CTRL,
6478     &parms[i][3]);
6479    }
6480    else if(plci->appl)
6481    {
6482     parms[i][0]=0; /* kill it */
6483     sendf(plci->appl,_MANUFACTURER_I,
6484     Id,
6485     0,
6486     "dwS",
6487     _DI_MANU_ID,
6488     _DI_SSEXT_CTRL,
6489     &parms[i][3]);
6490    }
6491     }
6492 };
6493 
6494 static void nl_ind(PLCI *plci)
6495 {
6496   byte ch;
6497   word ncci;
6498   dword Id;
6499   DIVA_CAPI_ADAPTER   * a;
6500   word NCCIcode;
6501   APPL   * APPLptr;
6502   word count;
6503   word Num;
6504   word i, ncpi_state;
6505   byte len, ncci_state;
6506   word msg;
6507   word info = 0;
6508   word fax_feature_bits;
6509   byte fax_send_edata_ack;
6510   static byte v120_header_buffer[2 + 3];
6511   static word fax_info[] = {
6512     0,                     /* T30_SUCCESS                        */
6513     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6514     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6516     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6517     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6518     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6519     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6520     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6521     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6522     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6523     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6524     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6525     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6526     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6527     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6528     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6529     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6530     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6531     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6532     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6533     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6534     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6535     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6536     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6537     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6538     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6539     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6540     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6541     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6542     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6543     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6544     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6545     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6546     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6547     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6548     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6549     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6550     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6551     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6552     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6553     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6554     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6555     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6556     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6557     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6558     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6559   };
6560 
6561     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6562 
6563 
6564   static word rtp_info[] = {
6565     GOOD,                  /* RTP_SUCCESS                       */
6566     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6567   };
6568 
6569   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6570   {
6571     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6572     0x00000000, 0x00000000, 0x00000000, 0x00000000
6573   };
6574 
6575   ch = plci->NL.IndCh;
6576   a = plci->adapter;
6577   ncci = a->ch_ncci[ch];
6578   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6579   if(plci->tel) Id|=EXT_CONTROLLER;
6580   APPLptr = plci->appl;
6581   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",
6582     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6583 
6584   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6585 
6586   if (plci->nl_remove_id)
6587   {
6588     plci->NL.RNR = 2; /* discard */
6589     dbug(1,dprintf("NL discard while remove pending"));
6590     return;
6591   }
6592   if((plci->NL.Ind &0x0f)==N_CONNECT)
6593   {
6594     if(plci->State==INC_DIS_PENDING
6595     || plci->State==OUTG_DIS_PENDING
6596     || plci->State==IDLE)
6597     {
6598       plci->NL.RNR = 2; /* discard */
6599       dbug(1,dprintf("discard n_connect"));
6600       return;
6601     }
6602     if(plci->State < INC_ACT_PENDING)
6603     {
6604       plci->NL.RNR = 1; /* flow control */
6605       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6606       return;
6607     }
6608   }
6609 
6610   if(!APPLptr)                         /* no application or invalid data */
6611   {                                    /* while reloading the DSP        */
6612     dbug(1,dprintf("discard1"));
6613     plci->NL.RNR = 2;
6614     return;
6615   }
6616 
6617   if (((plci->NL.Ind &0x0f) == N_UDATA)
6618      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6619         || (plci->B2_prot == 7)
6620         || (plci->B3_prot == 7)) )
6621   {
6622     plci->ncpi_buffer[0] = 0;
6623 
6624     ncpi_state = plci->ncpi_state;
6625     if (plci->NL.complete == 1)
6626     {
6627       byte  * data = &plci->NL.RBuffer->P[0];
6628 
6629       if ((plci->NL.RBuffer->length >= 12)
6630         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6631           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6632       {
6633         word conn_opt, ncpi_opt = 0x00;
6634 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6635 
6636         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6637           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6638         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6639           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6640 
6641         data++;    /* indication code */
6642         data += 2; /* timestamp */
6643         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6644           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6645         data++;    /* connected norm */
6646         conn_opt = GET_WORD(data);
6647         data += 2; /* connected options */
6648 
6649         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6650 
6651         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6652         {
6653           ncpi_opt |= MDM_NCPI_ECM_V42;
6654         }
6655         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6656         {
6657           ncpi_opt |= MDM_NCPI_ECM_MNP;
6658         }
6659         else
6660         {
6661           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6662         }
6663         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6664         {
6665           ncpi_opt |= MDM_NCPI_COMPRESSED;
6666         }
6667         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6668         plci->ncpi_buffer[0] = 4;
6669 
6670         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6671       }
6672     }
6673     if (plci->B3_prot == 7)
6674     {
6675       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6676        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6677        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6678       {
6679         a->ncci_state[ncci] = INC_ACT_PENDING;
6680         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6681         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6682       }
6683     }
6684 
6685     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6686         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6687      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6688      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6689 
6690     {
6691       plci->NL.RNR = 2;
6692       return;
6693     }
6694   }
6695 
6696   if(plci->NL.complete == 2)
6697     {
6698     if (((plci->NL.Ind &0x0f) == N_UDATA)
6699      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6700     {
6701       switch(plci->RData[0].P[0])
6702       {
6703 
6704       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6705         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6706           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6707         break;
6708       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6709         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6710           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6711         break;
6712       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6713         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714         break;
6715       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6716         dtmf_confirmation (Id, plci);
6717         break;
6718 
6719 
6720       case UDATA_INDICATION_MIXER_TAP_DATA:
6721         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6722  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6723  if (i != 0)
6724  {
6725    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6726           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6727  }
6728         break;
6729 
6730 
6731       case UDATA_INDICATION_MIXER_COEFS_SET:
6732         mixer_indication_coefs_set (Id, plci);
6733         break;
6734       case UDATA_INDICATION_XCONNECT_FROM:
6735         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6736         break;
6737       case UDATA_INDICATION_XCONNECT_TO:
6738         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6739         break;
6740 
6741 
6742       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6743         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6744         break;
6745 
6746 
6747 
6748       default:
6749         break;
6750       }
6751     }
6752     else
6753   {
6754       if ((plci->RData[0].PLength != 0)
6755      && ((plci->B2_prot == B2_V120_ASYNC)
6756       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6757       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6758     {
6759 
6760       sendf(plci->appl,_DATA_B3_I,Id,0,
6761             "dwww",
6762             plci->RData[1].P,
6763               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6764             plci->RNum,
6765             plci->RFlags);
6766 
6767     }
6768     else
6769     {
6770 
6771       sendf(plci->appl,_DATA_B3_I,Id,0,
6772             "dwww",
6773             plci->RData[0].P,
6774             plci->RData[0].PLength,
6775             plci->RNum,
6776             plci->RFlags);
6777 
6778     }
6779     }
6780     return;
6781   }
6782 
6783   fax_feature_bits = 0;
6784   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6785      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6786      (plci->NL.Ind &0x0f)==N_DISC ||
6787      (plci->NL.Ind &0x0f)==N_EDATA ||
6788      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6789   {
6790     info = 0;
6791     plci->ncpi_buffer[0] = 0;
6792     switch (plci->B3_prot) {
6793     case  0: /*XPARENT*/
6794     case  1: /*T.90 NL*/
6795       break;    /* no network control protocol info - jfr */
6796     case  2: /*ISO8202*/
6797     case  3: /*X25 DCE*/
6798       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6799       plci->ncpi_buffer[0] = (byte)(i+3);
6800       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6801       plci->ncpi_buffer[2] = 0;
6802       plci->ncpi_buffer[3] = 0;
6803       break;
6804     case  4: /*T.30 - FAX*/
6805     case  5: /*T.30 - FAX*/
6806       if(plci->NL.RLength>=sizeof(T30_INFO))
6807       {
6808         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6809         len = 9;
6810         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6811         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6812         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6813         if (plci->B3_prot == 5)
6814         {
6815           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6816             i |= 0x8000; /* This is not an ECM connection */
6817           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6818             i |= 0x4000; /* This is a connection with MMR compression */
6819           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6820             i |= 0x2000; /* This is a connection with MR compression */
6821           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6822             i |= 0x0004; /* More documents */
6823           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6824             i |= 0x0002; /* Fax-polling indication */
6825         }
6826         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6827         PUT_WORD(&(plci->ncpi_buffer[3]),i);
6828         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6829         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6830         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6831         plci->ncpi_buffer[len] = 0;
6832         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6833         {
6834           plci->ncpi_buffer[len] = 20;
6835           for (i = 0; i < 20; i++)
6836             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6837         }
6838         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6839         {
6840           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6841             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6842           else
6843             info = _FAX_PROTOCOL_ERROR;
6844         }
6845 
6846         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6847           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6848         {
6849           i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6850           while (i < plci->NL.RBuffer->length)
6851             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6852         }
6853 
6854         plci->ncpi_buffer[0] = len;
6855         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6856         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6857 
6858         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6859  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6860          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6861           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6862          || (((plci->NL.Ind &0x0f) == N_EDATA)
6863           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6864            || (((T30_INFO   *)plci->NL.RBuffer->