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 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 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 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] != 0)
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] != 0)
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 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1198 {
1199   word ch;
1200   word i;
1201   word Info;
1202   word CIP;
1203   byte LinkLayer;
1204   API_PARSE * ai;
1205   API_PARSE * bp;
1206     API_PARSE ai_parms[5];
1207   word channel = 0;
1208   dword ch_mask;
1209   byte m;
1210   static byte esc_chi[35] = {0x02,0x18,0x01};
1211   static byte lli[2] = {0x01,0x00};
1212   byte noCh = 0;
1213   word dir = 0;
1214   byte   *p_chi = "";
1215 
1216   for(i=0;i<5;i++) ai_parms[i].length = 0;
1217 
1218   dbug(1,dprintf("connect_req(%d)",parms->length));
1219   Info = _WRONG_IDENTIFIER;
1220   if(a)
1221   {
1222     if(a->adapter_disabled)
1223     {
1224       dbug(1,dprintf("adapter disabled"));
1225       Id = ((word)1<<8)|a->Id;
1226       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1227       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1228       return false;
1229     }
1230     Info = _OUT_OF_PLCI;
1231     if((i=get_plci(a)))
1232     {
1233       Info = 0;
1234       plci = &a->plci[i-1];
1235       plci->appl = appl;
1236       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1237       /* check 'external controller' bit for codec support */
1238       if(Id & EXT_CONTROLLER)
1239       {
1240         if(AdvCodecSupport(a, plci, appl, 0) )
1241         {
1242           plci->Id = 0;
1243           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1244           return 2;
1245         }
1246       }
1247       ai = &parms[9];
1248       bp = &parms[5];
1249       ch = 0;
1250       if(bp->length)LinkLayer = bp->info[3];
1251       else LinkLayer = 0;
1252       if(ai->length)
1253       {
1254         ch=0xffff;
1255         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1256         {
1257           ch = 0;
1258           if(ai_parms[0].length)
1259           {
1260             ch = GET_WORD(ai_parms[0].info+1);
1261             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1262             if(ch==4) /* explizit CHI in message */
1263             {
1264               /* check length of B-CH struct */
1265               if((ai_parms[0].info)[3]>=1)
1266               {
1267                 if((ai_parms[0].info)[4]==CHI)
1268                 {
1269                   p_chi = &((ai_parms[0].info)[5]);
1270                 }
1271                 else
1272                 {
1273                   p_chi = &((ai_parms[0].info)[3]);
1274                 }
1275                 if(p_chi[0]>35) /* check length of channel ID */
1276                 {
1277                   Info = _WRONG_MESSAGE_FORMAT;    
1278                 }
1279               }
1280               else Info = _WRONG_MESSAGE_FORMAT;    
1281             }
1282 
1283             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1284             {
1285               dir = GET_WORD(ai_parms[0].info+3);
1286               ch_mask = 0;
1287               m = 0x3f;
1288               for(i=0; i+5<=ai_parms[0].length; i++)
1289               {
1290                 if(ai_parms[0].info[i+5]!=0)
1291                 {
1292                   if((ai_parms[0].info[i+5] | m) != 0xff)
1293                     Info = _WRONG_MESSAGE_FORMAT;
1294                   else
1295                   {
1296                     if (ch_mask == 0)
1297                       channel = i;
1298                     ch_mask |= 1L << i;
1299                   }
1300                 }
1301                 m = 0;
1302               }
1303               if (ch_mask == 0)
1304                 Info = _WRONG_MESSAGE_FORMAT;
1305               if (!Info)
1306               {
1307                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1308                 {
1309                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1310                   for(i=0; i+5<=ai_parms[0].length; i++)
1311                     esc_chi[i+3] = ai_parms[0].info[i+5];
1312                 }
1313                 else
1314                   esc_chi[0] = 2;
1315                 esc_chi[2] = (byte)channel;
1316                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1317                 add_p(plci,LLI,lli);
1318                 add_p(plci,ESC,esc_chi);
1319                 plci->State = LOCAL_CONNECT;
1320                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1321               }
1322             }
1323           }
1324         }
1325         else  Info = _WRONG_MESSAGE_FORMAT;
1326       }
1327 
1328       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1329       plci->command = _CONNECT_R;
1330       plci->number = Number;
1331       /* x.31 or D-ch free SAPI in LinkLayer? */
1332       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1333       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1334       {
1335         /* B-channel used for B3 connections (ch==0), or no B channel    */
1336         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1337         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1338         else     Info = add_b1(plci,&parms[5],ch,0); 
1339         add_s(plci,OAD,&parms[2]);
1340         add_s(plci,OSA,&parms[4]);
1341         add_s(plci,BC,&parms[6]);
1342         add_s(plci,LLC,&parms[7]);
1343         add_s(plci,HLC,&parms[8]);
1344         CIP = GET_WORD(parms[0].info);
1345         if (a->Info_Mask[appl->Id-1] & 0x200)
1346         {
1347           /* early B3 connect (CIP mask bit 9) no release after a disc */
1348           add_p(plci,LLI,"\x01\x01");
1349         }
1350         if(GET_WORD(parms[0].info)<29) {
1351           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1352           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1353         }
1354         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1355         sig_req(plci,ASSIGN,DSIG_ID);
1356       }
1357       else if(ch==1) {
1358 
1359         /* D-Channel used for B3 connections */
1360         plci->Sig.Id = 0xff;
1361         Info = 0;
1362       }
1363 
1364       if(!Info && ch!=2 && !noCh ) {
1365         Info = add_b23(plci,&parms[5]);
1366         if(!Info) {
1367           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1368         }
1369       }
1370 
1371       if(!Info)
1372       {
1373         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1374         {
1375           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1376           {
1377             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1378             plci->spoofed_msg = CALL_REQ;
1379             plci->internal_command = BLOCK_PLCI;
1380             plci->command = 0;
1381             dbug(1,dprintf("Spoof"));
1382             send_req(plci);
1383             return false;
1384           }
1385           if(ch==4)add_p(plci,CHI,p_chi);
1386           add_s(plci,CPN,&parms[1]);
1387           add_s(plci,DSA,&parms[3]);
1388           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1389           add_ai(plci,&parms[9]);
1390           if(!dir)sig_req(plci,CALL_REQ,0);
1391           else
1392           {
1393             plci->command = PERM_LIST_REQ;
1394             plci->appl = appl;
1395             sig_req(plci,LISTEN_REQ,0);
1396             send_req(plci);
1397             return false;
1398           }
1399         }
1400         send_req(plci);
1401         return false;
1402       }
1403       plci->Id = 0;
1404     }
1405   }
1406   sendf(appl,
1407         _CONNECT_R|CONFIRM,
1408         Id,
1409         Number,
1410         "w",Info);
1411   return 2;
1412 }
1413 
1414 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1415 {
1416   word i, Info;
1417   word Reject;
1418   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1419   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1420   API_PARSE * ai;
1421     API_PARSE ai_parms[5];
1422   word ch=0;
1423 
1424   if(!plci) {
1425     dbug(1,dprintf("connect_res(no plci)"));
1426     return 0;  /* no plci, no send */
1427   }
1428 
1429   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1430   for(i=0;i<5;i++) ai_parms[i].length = 0;
1431   ai = &parms[5];
1432   dbug(1,dprintf("ai->length=%d",ai->length));
1433 
1434   if(ai->length)
1435   {
1436     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1437     {
1438       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1439       ch = 0;
1440       if(ai_parms[0].length)
1441       {
1442         ch = GET_WORD(ai_parms[0].info+1);
1443         dbug(1,dprintf("BCH-I=0x%x",ch));
1444       }
1445     }
1446   }
1447 
1448   if(plci->State==INC_CON_CONNECTED_ALERT)
1449   {
1450     dbug(1,dprintf("Connected Alert Call_Res"));
1451     if (a->Info_Mask[appl->Id-1] & 0x200)
1452     {
1453     /* early B3 connect (CIP mask bit 9) no release after a disc */
1454       add_p(plci,LLI,"\x01\x01");
1455     }
1456     add_s(plci, CONN_NR, &parms[2]);
1457     add_s(plci, LLC, &parms[4]);
1458     add_ai(plci, &parms[5]);
1459     plci->State = INC_CON_ACCEPT;
1460     sig_req(plci, CALL_RES,0);
1461     return 1;
1462   }
1463   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1464     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1465     dump_c_ind_mask (plci);
1466     Reject = GET_WORD(parms[0].info);
1467     dbug(1,dprintf("Reject=0x%x",Reject));
1468     if(Reject) 
1469     {
1470       if(c_ind_mask_empty (plci)) 
1471       {
1472         if((Reject&0xff00)==0x3400) 
1473         {
1474           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1475           add_p(plci,ESC,esc_t);
1476           add_ai(plci, &parms[5]);
1477           sig_req(plci,REJECT,0);
1478         }      
1479         else if(Reject==1 || Reject>9) 
1480         {
1481           add_ai(plci, &parms[5]);
1482           sig_req(plci,HANGUP,0);
1483         }
1484         else 
1485         {
1486           esc_t[2] = cau_t[(Reject&0x000f)];
1487           add_p(plci,ESC,esc_t);
1488           add_ai(plci, &parms[5]);
1489           sig_req(plci,REJECT,0);
1490         }
1491         plci->appl = appl;
1492       }
1493       else 
1494       {
1495         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1496       }
1497     }
1498     else {
1499       plci->appl = appl;
1500       if(Id & EXT_CONTROLLER){
1501         if(AdvCodecSupport(a, plci, appl, 0)){
1502           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1503           sig_req(plci,HANGUP,0);
1504           return 1;
1505         }
1506         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1507         {
1508           Info = add_b23(plci, &parms[1]);
1509           if (Info)
1510           {
1511             dbug(1,dprintf("connect_res(error from add_b23)"));
1512             sig_req(plci,HANGUP,0);
1513             return 1;
1514           }
1515           if(plci->adv_nl)
1516           {
1517             nl_req_ncci(plci, ASSIGN, 0);
1518           }
1519         }
1520       }
1521       else
1522       {
1523         plci->tel = 0;
1524         if(ch!=2)
1525         {
1526           Info = add_b23(plci, &parms[1]);
1527           if (Info)
1528           {
1529             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530             sig_req(plci,HANGUP,0);
1531             return 1;
1532           }
1533         }
1534         nl_req_ncci(plci, ASSIGN, 0);
1535       }
1536 
1537       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1538       {
1539         api_save_msg(parms, "wsssss", &plci->saved_msg);
1540         plci->spoofed_msg = CALL_RES;
1541         plci->internal_command = BLOCK_PLCI;
1542         plci->command = 0;
1543         dbug(1,dprintf("Spoof"));
1544       }
1545       else
1546       {
1547         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548         if (a->Info_Mask[appl->Id-1] & 0x200)
1549         {
1550           /* early B3 connect (CIP mask bit 9) no release after a disc */
1551           add_p(plci,LLI,"\x01\x01");
1552         }
1553         add_s(plci, CONN_NR, &parms[2]);
1554         add_s(plci, LLC, &parms[4]);
1555         add_ai(plci, &parms[5]);
1556         plci->State = INC_CON_ACCEPT;
1557         sig_req(plci, CALL_RES,0);
1558       }
1559 
1560       for(i=0; i<max_appl; i++) {
1561         if(test_c_ind_mask_bit (plci, i)) {
1562           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1563         }
1564       }
1565     }
1566   }
1567   return 1;
1568 }
1569 
1570 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1571 {
1572   dbug(1,dprintf("connect_a_res"));
1573   return false;
1574 }
1575 
1576 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1577 {
1578   word Info;
1579   word i;
1580 
1581   dbug(1,dprintf("disconnect_req"));
1582 
1583   Info = _WRONG_IDENTIFIER;
1584 
1585   if(plci)
1586   {
1587     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1588     {
1589       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1590       plci->appl = appl;
1591       for(i=0; i<max_appl; i++)
1592       {
1593         if(test_c_ind_mask_bit (plci, i))
1594           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595       }
1596       plci->State = OUTG_DIS_PENDING;
1597     }
1598     if(plci->Sig.Id && plci->appl)
1599     {
1600       Info = 0;
1601         if(plci->Sig.Id!=0xff)
1602         {
1603           if(plci->State!=INC_DIS_PENDING)
1604           {
1605             add_ai(plci, &msg[0]);
1606             sig_req(plci,HANGUP,0);
1607             plci->State = OUTG_DIS_PENDING;
1608             return 1;
1609           }
1610         }
1611         else
1612         {
1613           if (plci->NL.Id && !plci->nl_remove_id)
1614           {
1615             mixer_remove (plci);
1616             nl_req_ncci(plci,REMOVE,0);
1617           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1618           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619           plci->State = INC_DIS_PENDING;
1620           }
1621           return 1;
1622         }
1623       }
1624     }
1625 
1626   if(!appl)  return false;
1627   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1628   return false;
1629 }
1630 
1631 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1632 {
1633   dbug(1,dprintf("disconnect_res"));
1634   if(plci)
1635   {
1636         /* clear ind mask bit, just in case of collsion of          */
1637         /* DISCONNECT_IND and CONNECT_RES                           */
1638     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1639     ncci_free_receive_buffers (plci, 0);
1640     if(plci_remove_check(plci))
1641     {
1642       return 0;
1643     }
1644     if(plci->State==INC_DIS_PENDING
1645     || plci->State==SUSPENDING) {
1646       if(c_ind_mask_empty (plci)) {
1647         if(plci->State!=SUSPENDING)plci->State = IDLE;
1648         dbug(1,dprintf("chs=%d",plci->channels));
1649         if(!plci->channels) {
1650           plci_remove(plci);
1651         }
1652       }
1653     }
1654   }
1655   return 0;
1656 }
1657 
1658 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1659 {
1660   word Info;
1661   byte i;
1662 
1663   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1664 
1665   Info = _WRONG_IDENTIFIER;
1666   if(a) {
1667     Info = 0;
1668     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1669     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1670     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1671     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1672       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1673     }
1674 
1675     /* check if external controller listen and switch listen on or off*/
1676     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1677       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1678         dummy_plci.State = IDLE;
1679         a->codec_listen[appl->Id-1] = &dummy_plci;
1680         a->TelOAD[0] = (byte)(parms[3].length);
1681         for(i=1;parms[3].length>=i && i<22;i++) {
1682           a->TelOAD[i] = parms[3].info[i];
1683         }
1684         a->TelOAD[i] = 0;
1685         a->TelOSA[0] = (byte)(parms[4].length);
1686         for(i=1;parms[4].length>=i && i<22;i++) {
1687           a->TelOSA[i] = parms[4].info[i];
1688         }
1689         a->TelOSA[i] = 0;
1690       }
1691       else Info = 0x2002; /* wrong controller, codec not supported */
1692     }
1693     else{               /* clear listen */
1694       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1695     }
1696   }
1697   sendf(appl,
1698         _LISTEN_R|CONFIRM,
1699         Id,
1700         Number,
1701         "w",Info);
1702 
1703   if (a) listen_check(a);
1704   return false;
1705 }
1706 
1707 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1708 {
1709   word i;
1710   API_PARSE * ai;
1711   PLCI   * rc_plci = NULL;
1712     API_PARSE ai_parms[5];
1713   word Info = 0;
1714 
1715   dbug(1,dprintf("info_req"));
1716   for(i=0;i<5;i++) ai_parms[i].length = 0;
1717 
1718   ai = &msg[1];
1719 
1720   if(ai->length)
1721   {
1722     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1723     {
1724       dbug(1,dprintf("AddInfo wrong"));
1725       Info = _WRONG_MESSAGE_FORMAT;
1726     }
1727   }
1728   if(!a) Info = _WRONG_STATE;
1729 
1730   if(!Info && plci)
1731   {                /* no fac, with CPN, or KEY */
1732     rc_plci = plci;
1733     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1734     {
1735       /* overlap sending option */
1736       dbug(1,dprintf("OvlSnd"));
1737       add_s(plci,CPN,&msg[0]);
1738       add_s(plci,KEY,&ai_parms[1]);
1739       sig_req(plci,INFO_REQ,0);
1740       send_req(plci);
1741       return false;
1742     }
1743 
1744     if(plci->State && ai_parms[2].length)
1745     {
1746       /* User_Info option */
1747       dbug(1,dprintf("UUI"));
1748       add_s(plci,UUI,&ai_parms[2]);
1749       sig_req(plci,USER_DATA,0);
1750     }
1751     else if(plci->State && ai_parms[3].length)
1752     {
1753       /* Facility option */
1754       dbug(1,dprintf("FAC"));
1755       add_s(plci,CPN,&msg[0]);
1756       add_ai(plci, &msg[1]);
1757       sig_req(plci,FACILITY_REQ,0);
1758     }
1759     else
1760     {
1761       Info = _WRONG_STATE;
1762     }
1763   }
1764   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1765   {
1766     /* NCR_Facility option -> send UUI and Keypad too */
1767     dbug(1,dprintf("NCR_FAC"));
1768     if((i=get_plci(a)))
1769     {
1770       rc_plci = &a->plci[i-1];
1771       appl->NullCREnable  = true;
1772       rc_plci->internal_command = C_NCR_FAC_REQ;
1773       rc_plci->appl = appl;
1774       add_p(rc_plci,CAI,"\x01\x80");
1775       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1776       sig_req(rc_plci,ASSIGN,DSIG_ID);
1777       send_req(rc_plci);
1778     }
1779     else
1780     {
1781       Info = _OUT_OF_PLCI;
1782     }
1783 
1784     if(!Info)
1785     {
1786       add_s(rc_plci,CPN,&msg[0]);
1787       add_ai(rc_plci, &msg[1]);
1788       sig_req(rc_plci,NCR_FACILITY,0);
1789       send_req(rc_plci);
1790       return false;
1791      /* for application controlled supplementary services    */
1792     }
1793   }
1794 
1795   if (!rc_plci)
1796   {
1797     Info = _WRONG_MESSAGE_FORMAT;
1798   }
1799 
1800   if(!Info)
1801   {
1802     send_req(rc_plci);
1803   }
1804   else
1805   {  /* appl is not assigned to a PLCI or error condition */
1806     dbug(1,dprintf("localInfoCon"));
1807     sendf(appl,
1808           _INFO_R|CONFIRM,
1809           Id,
1810           Number,
1811           "w",Info);
1812   }
1813   return false;
1814 }
1815 
1816 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1817 {
1818   dbug(1,dprintf("info_res"));
1819   return false;
1820 }
1821 
1822 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1823 {
1824   word Info;
1825   byte ret;
1826 
1827   dbug(1,dprintf("alert_req"));
1828 
1829   Info = _WRONG_IDENTIFIER;
1830   ret = false;
1831   if(plci) {
1832     Info = _ALERT_IGNORED;
1833     if(plci->State!=INC_CON_ALERT) {
1834       Info = _WRONG_STATE;
1835       if(plci->State==INC_CON_PENDING) {
1836         Info = 0;
1837         plci->State=INC_CON_ALERT;
1838         add_ai(plci, &msg[0]);
1839         sig_req(plci,CALL_ALERT,0);
1840         ret = 1;
1841       }
1842     }
1843   }
1844   sendf(appl,
1845         _ALERT_R|CONFIRM,
1846         Id,
1847         Number,
1848         "w",Info);
1849   return ret;
1850 }
1851 
1852 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1853 {
1854   word Info = 0;
1855   word i    = 0;
1856 
1857   word selector;
1858   word SSreq;
1859   long relatedPLCIvalue;
1860   DIVA_CAPI_ADAPTER   * relatedadapter;
1861   byte * SSparms  = "";
1862     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1863     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1864   API_PARSE * parms;
1865     API_PARSE ss_parms[11];
1866   PLCI   *rplci;
1867     byte cai[15];
1868   dword d;
1869     API_PARSE dummy;
1870 
1871   dbug(1,dprintf("facility_req"));
1872   for(i=0;i<9;i++) ss_parms[i].length = 0;
1873 
1874   parms = &msg[1];
1875 
1876   if(!a)
1877   {
1878     dbug(1,dprintf("wrong Ctrl"));
1879     Info = _WRONG_IDENTIFIER;
1880   }
1881 
1882   selector = GET_WORD(msg[0].info);
1883 
1884   if(!Info)
1885   {
1886     switch(selector)
1887     {
1888       case SELECTOR_HANDSET:
1889         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1890         break;
1891 
1892       case SELECTOR_SU_SERV:
1893         if(!msg[1].length)
1894         {
1895           Info = _WRONG_MESSAGE_FORMAT;
1896           break;
1897         }
1898         SSreq = GET_WORD(&(msg[1].info[1]));
1899         PUT_WORD(&RCparms[1],SSreq);
1900         SSparms = RCparms;
1901         switch(SSreq)
1902         {
1903           case S_GET_SUPPORTED_SERVICES:
1904             if((i=get_plci(a)))
1905             {
1906               rplci = &a->plci[i-1];
1907               rplci->appl = appl;
1908               add_p(rplci,CAI,"\x01\x80");
1909               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1910               sig_req(rplci,ASSIGN,DSIG_ID);
1911               send_req(rplci);
1912             }
1913             else
1914             {
1915               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1916               SSparms = (byte *)SSstruct;
1917               break;
1918             }
1919             rplci->internal_command = GETSERV_REQ_PEND;
1920             rplci->number = Number;
1921             rplci->appl = appl;
1922             sig_req(rplci,S_SUPPORTED,0);
1923             send_req(rplci);
1924             return false;
1925             break;
1926 
1927           case S_LISTEN:
1928             if(parms->length==7)
1929             {
1930               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1931               {
1932                 dbug(1,dprintf("format wrong"));
1933                 Info = _WRONG_MESSAGE_FORMAT;
1934                 break;
1935               }
1936             }
1937             else
1938             {
1939               Info = _WRONG_MESSAGE_FORMAT;
1940               break;
1941             }
1942             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1943             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1944             {
1945               if((i=get_plci(a)))
1946               {
1947                 rplci = &a->plci[i-1];
1948                 rplci->appl = appl;
1949                 add_p(rplci,CAI,"\x01\x80");
1950                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1951                 sig_req(rplci,ASSIGN,DSIG_ID);
1952                 send_req(rplci);
1953               }
1954               else
1955               {
1956                 break;
1957               }
1958               rplci->internal_command = GET_MWI_STATE;
1959               rplci->number = Number;
1960               sig_req(rplci,MWI_POLL,0);
1961               send_req(rplci);
1962             }
1963             break;
1964 
1965           case S_HOLD:
1966             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1967             if(plci && plci->State && plci->SuppState==IDLE)
1968             {
1969               plci->SuppState = HOLD_REQUEST;
1970               plci->command = C_HOLD_REQ;
1971               add_s(plci,CAI,&ss_parms[1]);
1972               sig_req(plci,CALL_HOLD,0);
1973               send_req(plci);
1974               return false;
1975             }
1976             else Info = 0x3010;                    /* wrong state           */
1977             break;
1978           case S_RETRIEVE:
1979             if(plci && plci->State && plci->SuppState==CALL_HELD)
1980             {
1981               if(Id & EXT_CONTROLLER)
1982               {
1983                 if(AdvCodecSupport(a, plci, appl, 0))
1984                 {
1985                   Info = 0x3010;                    /* wrong state           */
1986                   break;
1987                 }
1988               }
1989               else plci->tel = 0;
1990 
1991               plci->SuppState = RETRIEVE_REQUEST;
1992               plci->command = C_RETRIEVE_REQ;
1993               if(plci->spoofed_msg==SPOOFING_REQUIRED)
1994               {
1995                 plci->spoofed_msg = CALL_RETRIEVE;
1996                 plci->internal_command = BLOCK_PLCI;
1997                 plci->command = 0;
1998                 dbug(1,dprintf("Spoof"));
1999                 return false;
2000               }
2001               else
2002               {
2003                 sig_req(plci,CALL_RETRIEVE,0);
2004                 send_req(plci);
2005                 return false;
2006               }
2007             }
2008             else Info = 0x3010;                    /* wrong state           */
2009             break;
2010           case S_SUSPEND:
2011             if(parms->length)
2012             {
2013               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2014               {
2015                 dbug(1,dprintf("format wrong"));
2016                 Info = _WRONG_MESSAGE_FORMAT;
2017                 break;
2018               }
2019             }
2020             if(plci && plci->State)
2021             {
2022               add_s(plci,CAI,&ss_parms[2]);
2023               plci->command = SUSPEND_REQ;
2024               sig_req(plci,SUSPEND,0);
2025               plci->State = SUSPENDING;
2026               send_req(plci);
2027             }
2028             else Info = 0x3010;                    /* wrong state           */
2029             break;
2030 
2031           case S_RESUME:
2032             if(!(i=get_plci(a)) )
2033             {
2034               Info = _OUT_OF_PLCI;
2035               break;
2036             }
2037             rplci = &a->plci[i-1];
2038             rplci->appl = appl;
2039             rplci->number = Number;
2040             rplci->tel = 0;
2041             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2042             /* check 'external controller' bit for codec support */
2043             if(Id & EXT_CONTROLLER)
2044             {
2045               if(AdvCodecSupport(a, rplci, appl, 0) )
2046               {
2047                 rplci->Id = 0;
2048                 Info = 0x300A;
2049                 break;
2050               }
2051             }
2052             if(parms->length)
2053             {
2054               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2055               {
2056                 dbug(1,dprintf("format wrong"));
2057                 rplci->Id = 0;
2058                 Info = _WRONG_MESSAGE_FORMAT;
2059                 break;
2060               }
2061             }
2062             dummy.length = 0;
2063             dummy.info = "\x00";
2064             add_b1(rplci, &dummy, 0, 0);
2065             if (a->Info_Mask[appl->Id-1] & 0x200)
2066             {
2067               /* early B3 connect (CIP mask bit 9) no release after a disc */
2068               add_p(rplci,LLI,"\x01\x01");
2069             }
2070             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2071             sig_req(rplci,ASSIGN,DSIG_ID);
2072             send_req(rplci);
2073             add_s(rplci,CAI,&ss_parms[2]);
2074             rplci->command = RESUME_REQ;
2075             sig_req(rplci,RESUME,0);
2076             rplci->State = RESUMING;
2077             send_req(rplci);
2078             break;
2079 
2080           case S_CONF_BEGIN: /* Request */
2081           case S_CONF_DROP:
2082           case S_CONF_ISOLATE:
2083           case S_CONF_REATTACH:
2084             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2085             {
2086               dbug(1,dprintf("format wrong"));
2087               Info = _WRONG_MESSAGE_FORMAT;
2088               break;
2089             }
2090             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2091             {
2092               d = GET_DWORD(ss_parms[2].info);     
2093               if(d>=0x80)
2094               {
2095                 dbug(1,dprintf("format wrong"));
2096                 Info = _WRONG_MESSAGE_FORMAT;
2097                 break;
2098               }
2099               plci->ptyState = (byte)SSreq;
2100               plci->command = 0;
2101               cai[0] = 2;
2102               switch(SSreq)
2103               {
2104               case S_CONF_BEGIN:
2105                   cai[1] = CONF_BEGIN;
2106                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2107                   break;
2108               case S_CONF_DROP:
2109                   cai[1] = CONF_DROP;
2110                   plci->internal_command = CONF_DROP_REQ_PEND;
2111                   break;
2112               case S_CONF_ISOLATE:
2113                   cai[1] = CONF_ISOLATE;
2114                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2115                   break;
2116               case S_CONF_REATTACH:
2117                   cai[1] = CONF_REATTACH;
2118                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2119                   break;
2120               }
2121               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2122               add_p(plci,CAI,cai);
2123               sig_req(plci,S_SERVICE,0);
2124               send_req(plci);
2125               return false;
2126             }
2127             else Info = 0x3010;                    /* wrong state           */
2128             break;
2129 
2130           case S_ECT:
2131           case S_3PTY_BEGIN:
2132           case S_3PTY_END:
2133           case S_CONF_ADD:
2134             if(parms->length==7)
2135             {
2136               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2137               {
2138                 dbug(1,dprintf("format wrong"));
2139                 Info = _WRONG_MESSAGE_FORMAT;
2140                 break;
2141               }
2142             }
2143             else if(parms->length==8) /* workaround for the T-View-S */
2144             {
2145               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2146               {
2147                 dbug(1,dprintf("format wrong"));
2148                 Info = _WRONG_MESSAGE_FORMAT;
2149                 break;
2150               }
2151             }
2152             else
2153             {
2154               Info = _WRONG_MESSAGE_FORMAT;
2155               break;
2156             }
2157             if(!msg[1].length)
2158             {
2159               Info = _WRONG_MESSAGE_FORMAT;
2160               break;
2161             }
2162             if (!plci)
2163             {
2164               Info = _WRONG_IDENTIFIER;
2165               break;
2166             }
2167             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2168             relatedPLCIvalue &= 0x0000FFFF;
2169             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2170             /* controller starts with 0 up to (max_adapter - 1) */
2171             if (((relatedPLCIvalue & 0x7f) == 0)
2172              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2173              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2174             {
2175               if(SSreq==S_3PTY_END)
2176               {
2177                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2178                 rplci = plci;
2179               }
2180               else
2181               {
2182                 Info = 0x3010;                    /* wrong state           */
2183                 break;
2184               }
2185             }
2186             else
2187             {  
2188               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2189               relatedPLCIvalue >>=8;
2190               /* find PLCI PTR*/
2191               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2192               {
2193                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2194                 {
2195                   rplci = &relatedadapter->plci[i];
2196                 }
2197               }
2198               if(!rplci || !relatedPLCIvalue)
2199               {
2200                 if(SSreq==S_3PTY_END)
2201                 {
2202                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2203                   rplci = plci;
2204                 }
2205                 else
2206                 {
2207                   Info = 0x3010;                    /* wrong state           */
2208                   break;
2209                 }
2210               }
2211             }
2212 /*
2213             dbug(1,dprintf("rplci:%x",rplci));
2214             dbug(1,dprintf("plci:%x",plci));
2215             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2216             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2217             dbug(1,dprintf("SSreq:%x",SSreq));
2218             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2219             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2220             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2221 */
2222             /* send PTY/ECT req, cannot check all states because of US stuff */
2223             if( !rplci->internal_command && rplci->appl )
2224             {
2225               plci->command = 0;
2226               rplci->relatedPTYPLCI = plci;
2227               plci->relatedPTYPLCI = rplci;
2228               rplci->ptyState = (byte)SSreq;
2229               if(SSreq==S_ECT)
2230               {
2231                 rplci->internal_command = ECT_REQ_PEND;
2232                 cai[1] = ECT_EXECUTE;
2233 
2234                 rplci->vswitchstate=0;
2235                 rplci->vsprot=0;
2236                 rplci->vsprotdialect=0;
2237                 plci->vswitchstate=0;
2238                 plci->vsprot=0;
2239                 plci->vsprotdialect=0;
2240 
2241               }
2242               else if(SSreq==S_CONF_ADD)
2243               {
2244                 rplci->internal_command = CONF_ADD_REQ_PEND;
2245                 cai[1] = CONF_ADD;
2246               }
2247               else
2248               {
2249                 rplci->internal_command = PTY_REQ_PEND;
2250                 cai[1] = (byte)(SSreq-3);
2251               }
2252               rplci->number = Number;
2253               if(plci!=rplci) /* explicit invocation */
2254               {
2255                 cai[0] = 2;
2256                 cai[2] = plci->Sig.Id;
2257                 dbug(1,dprintf("explicit invocation"));
2258               }
2259               else
2260               {
2261                 dbug(1,dprintf("implicit invocation"));
2262                 cai[0] = 1;
2263               }
2264               add_p(rplci,CAI,cai);
2265               sig_req(rplci,S_SERVICE,0);
2266               send_req(rplci);
2267               return false;
2268             }
2269             else
2270             {
2271               dbug(0,dprintf("Wrong line"));
2272               Info = 0x3010;                    /* wrong state           */
2273               break;
2274             }
2275             break;
2276 
2277           case S_CALL_DEFLECTION:
2278             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2279             {
2280               dbug(1,dprintf("format wrong"));
2281               Info = _WRONG_MESSAGE_FORMAT;
2282               break;
2283             }
2284             if (!plci)
2285             {
2286               Info = _WRONG_IDENTIFIER;
2287               break;
2288             }
2289             /* reuse unused screening indicator */
2290             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2291             plci->command = 0;
2292             plci->internal_command = CD_REQ_PEND;
2293             appl->CDEnable = true;
2294             cai[0] = 1;
2295             cai[1] = CALL_DEFLECTION;
2296             add_p(plci,CAI,cai);
2297             add_p(plci,CPN,ss_parms[3].info);
2298             sig_req(plci,S_SERVICE,0);
2299             send_req(plci);
2300             return false;
2301             break;
2302 
2303           case S_CALL_FORWARDING_START:
2304             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2305             {
2306               dbug(1,dprintf("format wrong"));
2307               Info = _WRONG_MESSAGE_FORMAT;
2308               break;
2309             }
2310 
2311             if((i=get_plci(a)))
2312             {
2313               rplci = &a->plci[i-1];
2314               rplci->appl = appl;
2315               add_p(rplci,CAI,"\x01\x80");
2316               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2317               sig_req(rplci,ASSIGN,DSIG_ID);
2318               send_req(rplci);
2319             }
2320             else
2321             {
2322               Info = _OUT_OF_PLCI;
2323               break;
2324             }
2325 
2326             /* reuse unused screening indicator */
2327             rplci->internal_command = CF_START_PEND;
2328             rplci->appl = appl;
2329             rplci->number = Number;
2330             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2331             cai[0] = 2;
2332             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2333             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334             add_p(rplci,CAI,cai);
2335             add_p(rplci,OAD,ss_parms[5].info);
2336             add_p(rplci,CPN,ss_parms[6].info);
2337             sig_req(rplci,S_SERVICE,0);
2338             send_req(rplci);
2339             return false;
2340             break;
2341 
2342           case S_INTERROGATE_DIVERSION:
2343           case S_INTERROGATE_NUMBERS:
2344           case S_CALL_FORWARDING_STOP:
2345           case S_CCBS_REQUEST:
2346           case S_CCBS_DEACTIVATE:
2347           case S_CCBS_INTERROGATE:
2348             switch(SSreq)
2349             {
2350             case S_INTERROGATE_NUMBERS:
2351                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2352                 {
2353                   dbug(0,dprintf("format wrong"));
2354                   Info = _WRONG_MESSAGE_FORMAT;
2355                 }
2356                 break;
2357             case S_CCBS_REQUEST:
2358             case S_CCBS_DEACTIVATE:
2359                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2360                 {
2361                   dbug(0,dprintf("format wrong"));
2362                   Info = _WRONG_MESSAGE_FORMAT;
2363                 }
2364                 break;
2365             case S_CCBS_INTERROGATE:
2366                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2367                 {
2368                   dbug(0,dprintf("format wrong"));
2369                   Info = _WRONG_MESSAGE_FORMAT;
2370                 }
2371                 break;
2372             default:
2373             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2374             {
2375               dbug(0,dprintf("format wrong"));
2376               Info = _WRONG_MESSAGE_FORMAT;
2377               break;
2378             }
2379                 break;
2380             }
2381 
2382             if(Info) break;
2383             if((i=get_plci(a)))
2384             {
2385               rplci = &a->plci[i-1];
2386               switch(SSreq)
2387               {
2388                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2389                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2390                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2391                   break;
2392                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2393                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2394                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2395                   break;
2396                 case S_CALL_FORWARDING_STOP:
2397                   rplci->internal_command = CF_STOP_PEND;
2398                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2399                   break;
2400                 case S_CCBS_REQUEST:
2401                   cai[1] = CCBS_REQUEST;
2402                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2403                   break;
2404                 case S_CCBS_DEACTIVATE:
2405                   cai[1] = CCBS_DEACTIVATE;
2406                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2407                   break;
2408                 case S_CCBS_INTERROGATE:
2409                   cai[1] = CCBS_INTERROGATE;
2410                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2411                   break;
2412                 default:
2413                   cai[1] = 0;
2414                 break;
2415               }
2416               rplci->appl = appl;
2417               rplci->number = Number;
2418               add_p(rplci,CAI,"\x01\x80");
2419               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2420               sig_req(rplci,ASSIGN,DSIG_ID);
2421               send_req(rplci);
2422             }
2423             else
2424             {
2425               Info = _OUT_OF_PLCI;
2426               break;
2427             }
2428 
2429             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2430             switch(SSreq)
2431             {
2432             case S_INTERROGATE_NUMBERS:
2433                 cai[0] = 1;
2434                 add_p(rplci,CAI,cai);
2435                 break;
2436             case S_CCBS_REQUEST:
2437             case S_CCBS_DEACTIVATE:
2438                 cai[0] = 3;
2439                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2440                 add_p(rplci,CAI,cai);
2441                 break;
2442             case S_CCBS_INTERROGATE:
2443                 cai[0] = 3;
2444                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2445                 add_p(rplci,CAI,cai);
2446                 add_p(rplci,OAD,ss_parms[4].info);
2447                 break;
2448             default:
2449             cai[0] = 2;
2450             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2451             add_p(rplci,CAI,cai);
2452             add_p(rplci,OAD,ss_parms[5].info);
2453                 break;
2454             }
2455                         
2456             sig_req(rplci,S_SERVICE,0);
2457             send_req(rplci);
2458             return false;
2459             break;
2460 
2461           case S_MWI_ACTIVATE:
2462             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2463             {
2464               dbug(1,dprintf("format wrong"));
2465               Info = _WRONG_MESSAGE_FORMAT;
2466               break;
2467             }
2468             if(!plci)
2469             {                               
2470               if((i=get_plci(a)))
2471               {
2472                 rplci = &a->plci[i-1];
2473                 rplci->appl = appl;
2474                 rplci->cr_enquiry=true;
2475                 add_p(rplci,CAI,"\x01\x80");
2476                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2477                 sig_req(rplci,ASSIGN,DSIG_ID);
2478                 send_req(rplci);
2479               }
2480               else
2481               {
2482                 Info = _OUT_OF_PLCI;
2483                 break;
2484               }
2485             }
2486             else
2487             {
2488               rplci = plci;
2489               rplci->cr_enquiry=false;
2490             }
2491 
2492             rplci->command = 0;
2493             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2494             rplci->appl = appl;
2495             rplci->number = Number;
2496 
2497             cai[0] = 13;
2498             cai[1] = ACTIVATION_MWI; /* Function */
2499             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2500             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2501             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2502             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2503             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2504             add_p(rplci,CAI,cai);
2505             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2506             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2507             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2508             add_p(rplci,UID,ss_parms[10].info); /* Time */
2509             sig_req(rplci,S_SERVICE,0);
2510             send_req(rplci);
2511             return false;
2512 
2513           case S_MWI_DEACTIVATE:
2514             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2515             {
2516               dbug(1,dprintf("format wrong"));
2517               Info = _WRONG_MESSAGE_FORMAT;
2518               break;
2519             }
2520             if(!plci)
2521             {                               
2522               if((i=get_plci(a)))
2523               {
2524                 rplci = &a->plci[i-1];
2525                 rplci->appl = appl;
2526                 rplci->cr_enquiry=true;
2527                 add_p(rplci,CAI,"\x01\x80");
2528                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2529                 sig_req(rplci,ASSIGN,DSIG_ID);
2530                 send_req(rplci);
2531               }
2532               else
2533               {
2534                 Info = _OUT_OF_PLCI;
2535                 break;
2536               }
2537             }
2538             else
2539             {
2540               rplci = plci;
2541               rplci->cr_enquiry=false;
2542             }
2543 
2544             rplci->command = 0;
2545             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2546             rplci->appl = appl;
2547             rplci->number = Number;
2548 
2549             cai[0] = 5;
2550             cai[1] = DEACTIVATION_MWI; /* Function */
2551             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2552             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2553             add_p(rplci,CAI,cai);
2554             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2555             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2556             sig_req(rplci,S_SERVICE,0);
2557             send_req(rplci);
2558             return false;
2559 
2560           default:
2561             Info = 0x300E;  /* not supported */
2562             break;
2563         }
2564         break; /* case SELECTOR_SU_SERV: end */
2565 
2566 
2567       case SELECTOR_DTMF:
2568         return (dtmf_request (Id, Number, a, plci, appl, msg));
2569 
2570 
2571 
2572       case SELECTOR_LINE_INTERCONNECT:
2573         return (mixer_request (Id, Number, a, plci, appl, msg));
2574 
2575 
2576 
2577       case PRIV_SELECTOR_ECHO_CANCELLER:
2578         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2579         return (ec_request (Id, Number, a, plci, appl, msg));
2580 
2581       case SELECTOR_ECHO_CANCELLER:
2582         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2583         return (ec_request (Id, Number, a, plci, appl, msg));
2584 
2585 
2586       case SELECTOR_V42BIS:
2587       default:
2588         Info = _FACILITY_NOT_SUPPORTED;
2589         break;
2590     } /* end of switch(selector) */
2591   }
2592 
2593   dbug(1,dprintf("SendFacRc"));
2594   sendf(appl,
2595         _FACILITY_R|CONFIRM,
2596         Id,
2597         Number,
2598         "wws",Info,selector,SSparms);
2599   return false;
2600 }
2601 
2602 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
2603 {
2604   dbug(1,dprintf("facility_res"));
2605   return false;
2606 }
2607 
2608 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2609 {
2610   word Info = 0;
2611   byte req;
2612   byte len;
2613   word w;
2614   word fax_control_bits, fax_feature_bits, fax_info_change;
2615   API_PARSE * ncpi;
2616     byte pvc[2];
2617 
2618     API_PARSE fax_parms[9];
2619   word i;
2620 
2621 
2622   dbug(1,dprintf("connect_b3_req"));
2623   if(plci)
2624   {
2625     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2626      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2627     {
2628       Info = _WRONG_STATE;
2629     }
2630     else
2631     {
2632       /* local reply if assign unsuccessfull
2633          or B3 protocol allows only one layer 3 connection
2634            and already connected
2635              or B2 protocol not any LAPD
2636                and connect_b3_req contradicts originate/answer direction */
2637       if (!plci->NL.Id
2638        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2639         && ((plci->channels != 0)
2640          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2641           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2642       {
2643         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2644                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2645         Info = _WRONG_STATE;
2646         sendf(appl,                                                        
2647               _CONNECT_B3_R|CONFIRM,
2648               Id,
2649               Number,
2650               "w",Info);
2651         return false;
2652       }
2653       plci->requested_options_conn = 0;
2654 
2655       req = N_CONNECT;
2656       ncpi = &parms[0];
2657       if(plci->B3_prot==2 || plci->B3_prot==3)
2658       {
2659         if(ncpi->length>2)
2660         {
2661           /* check for PVC */
2662           if(ncpi->info[2] || ncpi->info[3])
2663           {
2664             pvc[0] = ncpi->info[3];
2665             pvc[1] = ncpi->info[2];
2666             add_d(plci,2,pvc);
2667             req = N_RESET;
2668           }
2669           else
2670           {
2671             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2672             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2673           }
2674         }
2675       }
2676       else if(plci->B3_prot==5)
2677       {
2678         if (plci->NL.Id && !plci->nl_remove_id)
2679         {
2680           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2681           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2682           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2683            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2684           {
2685             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2686             fax_info_change = false;
2687             if (ncpi->length >= 4)
2688             {
2689               w = GET_WORD(&ncpi->info[3]);
2690               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2691               {
2692                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2693                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2694                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2695                 fax_info_change = true;
2696               }
2697               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2698               if (w & 0x0002)  /* Fax-polling request */
2699                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2700               if ((w & 0x0004) /* Request to send / poll another document */
2701                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2702               {
2703                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2704               }
2705               if (ncpi->length >= 6)
2706               {
2707                 w = GET_WORD(&ncpi->info[5]);
2708                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2709                 {
2710                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2711                   fax_info_change = true;
2712                 }
2713 
2714                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2715                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2716                 {
2717                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2718                 }
2719                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2720                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2721                 {
2722                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2723                 }
2724                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2725                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2726                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2727                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2728                 {
2729                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2730                     Info = _WRONG_MESSAGE_FORMAT;
2731                   else
2732                   {
2733                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2735       {
2736                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2737                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2738                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2739       }
2740                     w = fax_parms[4].length;
2741                     if (w > 20)
2742                       w = 20;
2743                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2744                     for (i = 0; i < w; i++)
2745                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2746                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2747                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2748                     w = fax_parms[5].length;
2749                     if (w > 20)
2750                       w = 20;
2751                     plci->fax_connect_info_buffer[len++] = (byte) w;
2752                     for (i = 0; i < w; i++)
2753                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2754                     w = fax_parms[6].length;
2755                     if (w > 20)
2756                       w = 20;
2757                     plci->fax_connect_info_buffer[len++] = (byte) w;
2758                     for (i = 0; i < w; i++)
2759                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2760                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2761                       & (1L << PRIVATE_FAX_NONSTANDARD))
2762       {
2763                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2764         {
2765                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2766                         plci->fax_connect_info_buffer[len++] = 0;
2767         }
2768                       else
2769                       {
2770           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2771             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2772    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2773           for (i = 0; i < fax_parms[7].length; i++)
2774      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2775                       }
2776                     }
2777                   }
2778                 }
2779                 else
2780                 {
2781                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2782                 }
2783                 fax_info_change = true;
2784 
2785               }
2786               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2787               {
2788                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2789                 fax_info_change = true;
2790               }
2791             }
2792             if (Info == GOOD)
2793             {
2794               plci->fax_connect_info_length = len;
2795               if (fax_info_change)
2796               {
2797                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2798                 {
2799                   start_internal_command (Id, plci, fax_connect_info_command);
2800                   return false;
2801                 }
2802                 else
2803                 {
2804                   start_internal_command (Id, plci, fax_adjust_b23_command);
2805                   return false;
2806                 }
2807               }
2808             }
2809           }
2810           else  Info = _WRONG_STATE;
2811         }
2812         else  Info = _WRONG_STATE;
2813       }
2814 
2815       else if (plci->B3_prot == B3_RTP)
2816       {
2817         plci->internal_req_buffer[0] = ncpi->length + 1;
2818         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2819         for (w = 0; w < ncpi->length; w++)
2820           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2821         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2822         return false;
2823       }
2824 
2825       if(!Info)
2826       {
2827         nl_req_ncci(plci,req,0);
2828         return 1;
2829       }
2830     }
2831   }
2832   else Info = _WRONG_IDENTIFIER;
2833 
2834   sendf(appl,
2835         _CONNECT_B3_R|CONFIRM,
2836         Id,
2837         Number,
2838         "w",Info);
2839   return false;
2840 }
2841 
2842 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2843 {
2844   word ncci;
2845   API_PARSE * ncpi;
2846   byte req;
2847 
2848   word w;
2849 
2850 
2851     API_PARSE fax_parms[9];
2852   word i;
2853   byte len;
2854 
2855 
2856   dbug(1,dprintf("connect_b3_res"));
2857 
2858   ncci = (word)(Id>>16);
2859   if(plci && ncci) {
2860     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2861       if (GET_WORD (&parms[0].info[0]) != 0)
2862       {
2863         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2864         channel_request_xon (plci, a->ncci_ch[ncci]);
2865         channel_xmit_xon (plci);
2866         cleanup_ncci_data (plci, ncci);
2867         nl_req_ncci(plci,N_DISC,(byte)ncci);
2868         return 1;
2869       }
2870       a->ncci_state[ncci] = INC_ACT_PENDING;
2871 
2872       req = N_CONNECT_ACK;
2873       ncpi = &parms[1];
2874       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2875       {
2876 
2877         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2878           & (1L << PRIVATE_FAX_NONSTANDARD))
2879  {
2880    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2881     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2882     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2883    {
2884             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2885             if (plci->fax_connect_info_length < len)
2886             {
2887               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2888               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2889             }
2890             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2891             {
2892               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2893             }
2894             else
2895             {
2896               if (plci->fax_connect_info_length <= len)
2897                 plci->fax_connect_info_buffer[len] = 0;
2898               len += 1 + plci->fax_connect_info_buffer[len];
2899               if (plci->fax_connect_info_length <= len)
2900                 plci->fax_connect_info_buffer[len] = 0;
2901               len += 1 + plci->fax_connect_info_buffer[len];
2902               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2903                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2904               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2905               for (i = 0; i < fax_parms[7].length; i++)
2906                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2907             }
2908             plci->fax_connect_info_length = len;
2909             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2910             start_internal_command (Id, plci, fax_connect_ack_command);
2911      return false;
2912           }
2913         }
2914 
2915         nl_req_ncci(plci,req,(byte)ncci);
2916         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2917          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2918         {
2919           if (plci->B3_prot == 4)
2920             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2921           else
2922             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2923           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2924         }
2925       }
2926 
2927       else if (plci->B3_prot == B3_RTP)
2928       {
2929         plci->internal_req_buffer[0] = ncpi->length + 1;
2930         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2931         for (w = 0; w < ncpi->length; w++)
2932           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2933         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2934         return false;
2935       }
2936 
2937       else
2938       {
2939         if(ncpi->length>2) {
2940           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2941           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2942         }
2943         nl_req_ncci(plci,req,(byte)ncci);
2944         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2945         if (plci->adjust_b_restore)
2946         {
2947           plci->adjust_b_restore = false;
2948           start_internal_command (Id, plci, adjust_b_restore);
2949         }
2950       }
2951       return 1;
2952     }
2953   }
2954   return false;
2955 }
2956 
2957 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2958 {
2959   word ncci;
2960 
2961   ncci = (word)(Id>>16);
2962   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2963 
2964   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2965    && (plci->State != OUTG_DIS_PENDING))
2966   {
2967     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2968       a->ncci_state[ncci] = CONNECTED;
2969       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2970       channel_request_xon (plci, a->ncci_ch[ncci]);
2971       channel_xmit_xon (plci);
2972     }
2973   }
2974   return false;
2975 }
2976 
2977 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2978 {
2979   word Info;
2980   word ncci;
2981   API_PARSE * ncpi;
2982 
2983   dbug(1,dprintf("disconnect_b3_req"));
2984 
2985   Info = _WRONG_IDENTIFIER;
2986   ncci = (word)(Id>>16);
2987   if (plci && ncci)
2988   {
2989     Info = _WRONG_STATE;
2990     if ((a->ncci_state[ncci] == CONNECTED)
2991      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2992      || (a->ncci_state[ncci] == INC_CON_PENDING)
2993      || (a->ncci_state[ncci] == INC_ACT_PENDING))
2994     {
2995       a->ncci_state[ncci] = OUTG_DIS_PENDING;
2996       channel_request_xon (plci, a->ncci_ch[ncci]);
2997       channel_xmit_xon (plci);
2998 
2999       if (a->ncci[ncci].data_pending
3000        && ((plci->B3_prot == B3_TRANSPARENT)
3001         || (plci->B3_prot == B3_T30)
3002         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3003       {
3004         plci->send_disc = (byte)ncci;
3005         plci->command = 0;
3006         return false;
3007       }
3008       else
3009       {
3010         cleanup_ncci_data (plci, ncci);
3011 
3012         if(plci->B3_prot==2 || plci->B3_prot==3)
3013         {
3014           ncpi = &parms[0];
3015           if(ncpi->length>3)
3016           {
3017             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3018           }
3019         }
3020         nl_req_ncci(plci,N_DISC,(byte)ncci);
3021       }
3022       return 1;
3023     }
3024   }
3025   sendf(appl,
3026         _DISCONNECT_B3_R|CONFIRM,
3027         Id,
3028         Number,
3029         "w",Info);
3030   return false;
3031 }
3032 
3033 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3034 {
3035   word ncci;
3036   word i;
3037 
3038   ncci = (word)(Id>>16);
3039   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3040   if(plci && ncci) {
3041     plci->requested_options_conn = 0;
3042     plci->fax_connect_info_length = 0;
3043     plci->ncpi_state = 0x00;
3044     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3045       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3046     {
3047       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3048     }
3049     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3050     if(i<MAX_CHANNELS_PER_PLCI) {
3051       if(plci->channels)plci->channels--;
3052       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3053       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3054 
3055       ncci_free_receive_buffers (plci, ncci);
3056 
3057       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3058         if(plci->State == SUSPENDING){
3059           sendf(plci->appl,
3060                 _FACILITY_I,
3061                 Id & 0xffffL,
3062                 0,
3063                 "ws", (word)3, "\x03\x04\x00\x00");
3064           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3065         }
3066         plci_remove(plci);
3067         plci->State=IDLE;
3068       }
3069     }
3070     else
3071     {
3072       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3073        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3074        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3075       {
3076         ncci_free_receive_buffers (plci, ncci);
3077 
3078         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3079 
3080         plci->adapter->ncci_state[ncci] = IDLE;
3081         start_internal_command (Id, plci, fax_disconnect_command);
3082         return 1;
3083       }
3084     }
3085   }
3086   return false;
3087 }
3088 
3089 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3090 {
3091   NCCI   *ncci_ptr;
3092   DATA_B3_DESC   *data;
3093   word Info;
3094   word ncci;
3095   word i;
3096 
3097   dbug(1,dprintf("data_b3_req"));
3098 
3099   Info = _WRONG_IDENTIFIER;
3100   ncci = (word)(Id>>16);
3101   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3102 
3103   if (plci && ncci)
3104   {
3105     Info = _WRONG_STATE;
3106     if ((a->ncci_state[ncci] == CONNECTED)
3107      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3108     {
3109         /* queue data */
3110       ncci_ptr = &(a->ncci[ncci]);
3111       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3112       if (i >= MAX_DATA_B3)
3113         i -= MAX_DATA_B3;
3114       data = &(ncci_ptr->DBuffer[i]);
3115       data->Number = Number;
3116       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3117        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3118       {
3119 
3120         data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3121 
3122       }
3123       else
3124         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3125       data->Length = GET_WORD(parms[1].info);
3126       data->Handle = GET_WORD(parms[2].info);
3127       data->Flags = GET_WORD(parms[3].info);
3128       (ncci_ptr->data_pending)++;
3129 
3130         /* check for delivery confirmation */
3131       if (data->Flags & 0x0004)
3132       {
3133         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3134         if (i >= MAX_DATA_ACK)
3135           i -= MAX_DATA_ACK;
3136         ncci_ptr->DataAck[i].Number = data->Number;
3137         ncci_ptr->DataAck[i].Handle = data->Handle;
3138         (ncci_ptr->data_ack_pending)++;
3139       }
3140 
3141       send_data(plci);
3142       return false;
3143     }
3144   }
3145   if (appl)
3146   {
3147     if (plci)
3148     {
3149       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3150        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3151       {
3152 
3153         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3154 
3155       }
3156     }
3157     sendf(appl,
3158           _DATA_B3_R|CONFIRM,
3159           Id,
3160           Number,
3161           "ww",GET_WORD(parms[2].info),Info);
3162   }
3163   return false;
3164 }
3165 
3166 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3167 {
3168   word n;
3169   word ncci;
3170   word NCCIcode;
3171 
3172   dbug(1,dprintf("data_b3_res"));
3173 
3174   ncci = (word)(Id>>16);
3175   if(plci && ncci) {
3176     n = GET_WORD(parms[0].info);
3177     dbug(1,dprintf("free(%d)",n));
3178     NCCIcode = ncci | (((word) a->Id) << 8);
3179     if(n<appl->MaxBuffer &&
3180        appl->DataNCCI[n]==NCCIcode &&
3181        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3182       dbug(1,dprintf("found"));
3183       appl->DataNCCI[n] = 0;
3184 
3185       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3186         channel_request_xon (plci, a->ncci_ch[ncci]);
3187       }
3188       channel_xmit_xon (plci);
3189 
3190       if(appl->DataFlags[n] &4) {
3191         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3192         return 1;
3193       }
3194     }
3195   }
3196   return false;
3197 }
3198 
3199 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3200 {
3201   word Info;
3202   word ncci;
3203 
3204   dbug(1,dprintf("reset_b3_req"));
3205 
3206   Info = _WRONG_IDENTIFIER;
3207   ncci = (word)(Id>>16);
3208   if(plci && ncci)
3209   {
3210     Info = _WRONG_STATE;
3211     switch (plci->B3_prot)
3212     {
3213     case B3_ISO8208:
3214     case B3_X25_DCE:
3215       if(a->ncci_state[ncci]==CONNECTED)
3216       {
3217         nl_req_ncci(plci,N_RESET,(byte)ncci);
3218         send_req(plci);
3219         Info = GOOD;
3220       }
3221       break;
3222     case B3_TRANSPARENT:
3223       if(a->ncci_state[ncci]==CONNECTED)
3224       {
3225         start_internal_command (Id, plci, reset_b3_command);
3226         Info = GOOD;
3227       }
3228       break;
3229     }
3230   }
3231   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3232   sendf(appl,
3233         _RESET_B3_R|CONFIRM,
3234         Id,
3235         Number,
3236         "w",Info);
3237   return false;
3238 }
3239 
3240 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3241 {
3242   word ncci;
3243 
3244   dbug(1,dprintf("reset_b3_res"));
3245 
3246   ncci = (word)(Id>>16);
3247   if(plci && ncci) {
3248     switch (plci->B3_prot)
3249     {
3250     case B3_ISO8208:
3251     case B3_X25_DCE:
3252       if(a->ncci_state[ncci]==INC_RES_PENDING)
3253       {
3254         a->ncci_state[ncci] = CONNECTED;
3255         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3256         return true;
3257       }
3258     break;
3259     }
3260   }
3261   return false;
3262 }
3263 
3264 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3265 {
3266   word ncci;
3267   API_PARSE * ncpi;
3268   byte req;
3269 
3270   dbug(1,dprintf("connect_b3_t90_a_res"));
3271 
3272   ncci = (word)(Id>>16);
3273   if(plci && ncci) {
3274     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3275       a->ncci_state[ncci] = CONNECTED;
3276     }
3277     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3278       a->ncci_state[ncci] = CONNECTED;
3279 
3280       req = N_CONNECT_ACK;
3281 
3282         /* parms[0]==0 for CAPI original message definition! */
3283       if(parms[0].info) {
3284         ncpi = &parms[1];
3285         if(ncpi->length>2) {
3286           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3287           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3288         }
3289       }
3290       nl_req_ncci(plci,req,(byte)ncci);
3291       return 1;
3292     }
3293   }
3294   return false;
3295 }
3296 
3297 
3298 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3299 {
3300   word Info=0;
3301   word i;
3302   byte tel;
3303     API_PARSE bp_parms[7];
3304 
3305   if(!plci || !msg)
3306   {
3307     Info = _WRONG_IDENTIFIER;
3308   }
3309   else
3310   {
3311     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3312                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3313     dbug(1,dprintf("PlciState=0x%x",plci->State));
3314     for(i=0;i<7;i++) bp_parms[i].length = 0;
3315 
3316     /* check if no channel is open, no B3 connected only */
3317     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3318      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3319     {
3320       Info = _WRONG_STATE;
3321     }
3322     /* check message format and fill bp_parms pointer */
3323     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3324     {
3325       Info = _WRONG_MESSAGE_FORMAT;
3326     }
3327     else
3328     {
3329       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3330       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3331         if(Id & EXT_CONTROLLER)
3332         {
3333           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3334           return 0;
3335         }
3336         plci->State=INC_CON_CONNECTED_ALERT;
3337         plci->appl = appl;
3338         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3339         dump_c_ind_mask (plci);
3340         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3341         {                         /* its quasi a connect        */
3342           if(test_c_ind_mask_bit (plci, i))
3343             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3344         }
3345       }
3346 
3347       api_save_msg(msg, "s", &plci->saved_msg);
3348       tel = plci->tel;
3349       if(Id & EXT_CONTROLLER)
3350       {
3351         if(tel) /* external controller in use by this PLCI */
3352         {
3353           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3354           {
3355             dbug(1,dprintf("Ext_Ctrl in use 1"));
3356             Info = _WRONG_STATE;
3357           }
3358         }
3359         else  /* external controller NOT in use by this PLCI ? */
3360         {
3361           if(a->AdvSignalPLCI)
3362           {
3363             dbug(1,dprintf("Ext_Ctrl in use 2"));
3364             Info = _WRONG_STATE;
3365           }
3366           else /* activate the codec */
3367           {
3368             dbug(1,dprintf("Ext_Ctrl start"));
3369             if(AdvCodecSupport(a, plci, appl, 0) )
3370             {
3371               dbug(1,dprintf("Error in codec procedures"));
3372               Info = _WRONG_STATE;
3373             }
3374             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3375             {
3376               plci->spoofed_msg = AWAITING_SELECT_B;
3377               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3378               plci->command = 0;
3379               dbug(1,dprintf("continue if codec loaded"));
3380               return false;
3381             }
3382           }
3383         }
3384       }
3385       else /* external controller bit is OFF */
3386       {
3387         if(tel) /* external controller in use, need to switch off */
3388         {
3389           if(a->AdvSignalAppl==appl)
3390           {
3391             CodecIdCheck(a, plci);
3392             plci->tel = 0;
3393             plci->adv_nl = 0;
3394             dbug(1,dprintf("Ext_Ctrl disable"));
3395           }
3396           else
3397           {
3398             dbug(1,dprintf("Ext_Ctrl not requested"));
3399           }
3400         }
3401       }
3402       if (!Info)
3403       {
3404         if (plci->call_dir & CALL_DIR_OUT)
3405           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3406         else if (plci->call_dir & CALL_DIR_IN)
3407           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3408         start_internal_command (Id, plci, select_b_command);
3409         return false;
3410       }
3411     }
3412   }
3413   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3414   return false;
3415 }
3416 
3417 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3418 {
3419   word command;
3420   word i;
3421   word ncci;
3422   API_PARSE * m;
3423     API_PARSE m_parms[5];
3424   word codec;
3425   byte req;
3426   byte ch;
3427   byte dir;
3428   static byte chi[2] = {0x01,0x00};
3429   static byte lli[2] = {0x01,0x00};
3430   static byte codec_cai[2] = {0x01,0x01};
3431   static byte null_msg = {0};
3432   static API_PARSE null_parms = { 0, &null_msg };
3433   PLCI   * v_plci;
3434   word Info=0;
3435 
3436   dbug(1,dprintf("manufacturer_req"));
3437   for(i=0;i<5;i++) m_parms[i].length = 0;
3438 
3439   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3440     Info = _WRONG_MESSAGE_FORMAT;
3441   }
3442   command = GET_WORD(parms[1].info);
3443   m = &parms[2];
3444   if (!Info)
3445   {
3446     switch(command) {
3447     case _DI_ASSIGN_PLCI:
3448       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3449         Info = _WRONG_MESSAGE_FORMAT;
3450         break;
3451       }
3452       codec = GET_WORD(m_parms[0].info);
3453       ch = m_parms[1].info[0];
3454       dir = m_parms[2].info[0];
3455       if((i=get_plci(a))) {
3456         plci = &a->plci[i-1];
3457         plci->appl = appl;
3458         plci->command = _MANUFACTURER_R;
3459         plci->m_command = command;
3460         plci->number = Number;
3461         plci->State = LOCAL_CONNECT;
3462         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3463         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3464 
3465         if((ch==1 || ch==2) && (dir<=2)) {
3466           chi[1] = (byte)(0x80|ch);
3467           lli[1] = 0;
3468           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3469           switch(codec)
3470           {
3471           case 0:
3472             Info = add_b1(plci,&m_parms[3],0,0);
3473             break;
3474           case 1:
3475             add_p(plci,CAI,codec_cai);
3476             break;
3477           /* manual 'swich on' to the codec support without signalling */
3478           /* first 'assign plci' with this function, then use */
3479           case 2:
3480             if(AdvCodecSupport(a, plci, appl, 0) ) {
3481               Info = _RESOURCE_ERROR;
3482             }
3483             else {
3484               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3485               lli[1] = 0x10; /* local call codec stream */
3486             }
3487             break;
3488           }
3489 
3490           plci->State = LOCAL_CONNECT;
3491           plci->manufacturer = true;
3492           plci->command = _MANUFACTURER_R;
3493           plci->m_command = command;
3494           plci->number = Number;
3495 
3496           if(!Info)
3497           {
3498             add_p(plci,LLI,lli);
3499             add_p(plci,CHI,chi);
3500             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3501             sig_req(plci,ASSIGN,DSIG_ID);
3502 
3503             if(!codec)
3504             {
3505               Info = add_b23(plci,&m_parms[3]);
3506               if(!Info)
3507               {
3508                 nl_req_ncci(plci,ASSIGN,0);
3509                 send_req(plci);
3510               }
3511             }
3512             if(!Info)
3513             {
3514               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3515               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3516               {
3517                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3518                 plci->spoofed_msg = AWAITING_MANUF_CON;
3519                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3520                 plci->command = 0;
3521                 send_req(plci);
3522                 return false;
3523               }
3524               if(dir==1) {
3525                 sig_req(plci,CALL_REQ,0);
3526               }
3527               else if(!dir){
3528                 sig_req(plci,LISTEN_REQ,0);
3529               }
3530               send_req(plci);
3531             }
3532             else
3533             {
3534               sendf(appl,
3535                     _MANUFACTURER_R|CONFIRM,
3536                     Id,
3537                     Number,
3538                     "dww",_DI_MANU_ID,command,Info);
3539               return 2;
3540             }
3541           }
3542         }
3543       }
3544       else  Info = _OUT_OF_PLCI;
3545       break;
3546 
3547     case _DI_IDI_CTRL:
3548       if(!plci)
3549       {
3550         Info = _WRONG_IDENTIFIER;
3551         break;
3552       }
3553       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3554         Info = _WRONG_MESSAGE_FORMAT;
3555         break;
3556       }
3557       req = m_parms[0].info[0];
3558       plci->command = _MANUFACTURER_R;
3559       plci->m_command = command;
3560       plci->number = Number;
3561       if(req==CALL_REQ)
3562       {
3563         plci->b_channel = getChannel(&m_parms[1]);
3564         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3565         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3566         {
3567           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3568           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3569           plci->command = 0;
3570           break;
3571         }
3572       }
3573       else if(req==LAW_REQ)
3574       {
3575         plci->cr_enquiry = true;
3576       }
3577       add_ss(plci,FTY,&m_parms[1]);
3578       sig_req(plci,req,0);
3579       send_req(plci);
3580       if(req==HANGUP)
3581       {      
3582         if (plci->NL.Id && !plci->nl_remove_id)
3583         {
3584           if (plci->channels)
3585           {
3586             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3587             {
3588               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3589               {
3590                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3591                 cleanup_ncci_data (plci, ncci);
3592                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3593               }
3594             }
3595           }
3596           mixer_remove (plci);
3597           nl_req_ncci(plci,REMOVE,0);
3598           send_req(plci);
3599         }  
3600       }
3601       break;
3602 
3603     case _DI_SIG_CTRL:
3604     /* signalling control for loop activation B-channel */
3605       if(!plci)
3606       {
3607         Info = _WRONG_IDENTIFIER;
3608         break;
3609       }
3610       if(m->length){
3611         plci->command = _MANUFACTURER_R;
3612         plci->number = Number;
3613         add_ss(plci,FTY,m);
3614         sig_req(plci,SIG_CTRL,0);
3615         send_req(plci);
3616       }
3617       else Info = _WRONG_MESSAGE_FORMAT;
3618       break;
3619 
3620     case _DI_RXT_CTRL:
3621     /* activation control for receiver/transmitter B-channel */
3622       if(!plci)
3623       {
3624         Info = _WRONG_IDENTIFIER;
3625         break;
3626       }
3627       if(m->length){
3628         plci->command = _MANUFACTURER_R;
3629         plci->number = Number;
3630         add_ss(plci,FTY,m);
3631         sig_req(plci,DSP_CTRL,0);
3632         send_req(plci);
3633       }
3634       else Info = _WRONG_MESSAGE_FORMAT;
3635       break;
3636 
3637     case _DI_ADV_CODEC:
3638     case _DI_DSP_CTRL:
3639       /* TEL_CTRL commands to support non standard adjustments: */
3640       /* Ring on/off, Handset micro volume, external micro vol. */
3641       /* handset+external speaker volume, receiver+transm. gain,*/
3642       /* handsfree on (hookinfo off), set mixer command         */
3643 
3644       if(command == _DI_ADV_CODEC)
3645       {
3646         if(!a->AdvCodecPLCI) {
3647           Info = _WRONG_STATE;
3648           break;
3649         }
3650         v_plci = a->AdvCodecPLCI;
3651       }
3652       else
3653       {
3654         if (plci
3655          && (m->length >= 3)
3656          && (m->info[1] == 0x1c)
3657          && (m->info[2] >= 1))
3658         {
3659           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3660           {
3661             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3662             {
3663               Info = _WRONG_STATE;
3664               break;
3665             }
3666             a->adv_voice_coef_length = m->info[2] - 1;
3667             if (a->adv_voice_coef_length > m->length - 3)
3668               a->adv_voice_coef_length = (byte)(m->length - 3);
3669             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3670               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3671             for (i = 0; i < a->adv_voice_coef_length; i++)
3672               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3673             if (plci->B1_facilities & B1_FACILITY_VOICE)
3674               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3675             break;
3676           }
3677           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3678           {
3679             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3680             {
3681               Info = _FACILITY_NOT_SUPPORTED;
3682               break;
3683             }
3684 
3685             plci->dtmf_parameter_length = m->info[2] - 1;
3686             if (plci->dtmf_parameter_length > m->length - 3)
3687               plci->dtmf_parameter_length = (byte)(m->length - 3);
3688             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3689               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3690             for (i = 0; i < plci->dtmf_parameter_length; i++)
3691               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3692             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3693               dtmf_parameter_write (plci);
3694             break;
3695 
3696           }
3697         }
3698         v_plci = plci;
3699       }
3700 
3701       if(!v_plci)
3702       {
3703         Info = _WRONG_IDENTIFIER;
3704         break;
3705       }
3706       if(m->length){
3707         add_ss(v_plci,FTY,m);
3708         sig_req(v_plci,TEL_CTRL,0);
3709         send_req(v_plci);
3710       }
3711       else Info = _WRONG_MESSAGE_FORMAT;
3712 
3713       break;
3714 
3715     case _DI_OPTIONS_REQUEST:
3716       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3717         Info = _WRONG_MESSAGE_FORMAT;
3718         break;
3719       }
3720       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3721       {
3722         Info = _FACILITY_NOT_SUPPORTED;
3723         break;
3724       }
3725       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3726       break;
3727 
3728 
3729 
3730     default:
3731       Info = _WRONG_MESSAGE_FORMAT;
3732       break;
3733     }
3734   }
3735 
3736   sendf(appl,
3737         _MANUFACTURER_R|CONFIRM,
3738         Id,
3739         Number,
3740         "dww",_DI_MANU_ID,command,Info);
3741   return false;
3742 }
3743 
3744 
3745 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3746 {
3747   word indication;
3748 
3749     API_PARSE m_parms[3];
3750   API_PARSE *ncpi;
3751     API_PARSE fax_parms[9];
3752   word i;
3753   byte len;
3754 
3755 
3756   dbug(1,dprintf("manufacturer_res"));
3757 
3758   if ((msg[0].length == 0)
3759    || (msg[1].length == 0)
3760    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3761   {
3762     return false;
3763   }
3764   indication = GET_WORD(msg[1].info);
3765   switch (indication)
3766   {
3767 
3768   case _DI_NEGOTIATE_B3:
3769     if(!plci)
3770       break;
3771     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3772      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3773     {
3774       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3775       break;
3776     }
3777     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3778     {
3779       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3780       break;
3781     }
3782     ncpi = &m_parms[1];
3783     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3784     if (plci->fax_connect_info_length < len)
3785     {
3786       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3787       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3788     }
3789     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3790     {
3791       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3792     }
3793     else
3794     {
3795       if (plci->fax_connect_info_length <= len)
3796         plci->fax_connect_info_buffer[len] = 0;
3797       len += 1 + plci->fax_connect_info_buffer[len];
3798       if (plci->fax_connect_info_length <= len)
3799         plci->fax_connect_info_buffer[len] = 0;
3800       len += 1 + plci->fax_connect_info_buffer[len];
3801       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3802         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3803       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3804       for (i = 0; i < fax_parms[7].length; i++)
3805         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3806     }
3807     plci->fax_connect_info_length = len;
3808     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3809     start_internal_command (Id, plci, fax_edata_ack_command);
3810     break;
3811 
3812   }
3813   return false;
3814 }
3815 
3816 /*------------------------------------------------------------------*/
3817 /* IDI callback function                                            */
3818 /*------------------------------------------------------------------*/
3819 
3820 void   callback(ENTITY   * e)
3821 {
3822   DIVA_CAPI_ADAPTER   * a;
3823   APPL   * appl;
3824   PLCI   * plci;
3825   CAPI_MSG   *m;
3826   word i, j;
3827   byte rc;
3828   byte ch;
3829   byte req;
3830   byte global_req;
3831   int no_cancel_rc;
3832 
3833   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3834                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3835 
3836   a = &(adapter[(byte)e->user[0]]);
3837   plci = &(a->plci[e->user[1]]);
3838   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3839 
3840   /*
3841      If new protocol code and new XDI is used then CAPI should work
3842      fully in accordance with IDI cpec an look on callback field instead
3843      of Rc field for return codes.
3844    */
3845   if (((e->complete == 0xff) && no_cancel_rc) ||
3846       (e->Rc && !no_cancel_rc)) {
3847     rc = e->Rc;
3848     ch = e->RcCh;
3849     req = e->Req;
3850     e->Rc = 0;
3851 
3852     if (e->user[0] & 0x8000)
3853     {
3854       /*
3855          If REMOVE request was sent then we have to wait until
3856          return code with Id set to zero arrives.
3857          All other return codes should be ignored.
3858          */
3859       if (req == REMOVE)
3860       {
3861         if (e->Id)
3862         {
3863           dbug(1,dprintf("cancel RC in REMOVE state"));
3864           return;
3865         }
3866         channel_flow_control_remove (plci);
3867         for (i = 0; i < 256; i++)
3868         {
3869           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3870             a->FlowControlIdTable[i] = 0;
3871         }
3872         plci->nl_remove_id = 0;
3873         if (plci->rx_dma_descriptor > 0) {
3874           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3875           plci->rx_dma_descriptor = 0;
3876         }
3877       }
3878       if (rc == OK_FC)
3879       {
3880         a->FlowControlIdTable[ch] = e->Id;
3881         a->FlowControlSkipTable[ch] = 0;
3882 
3883         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3884         a->ch_flow_plci[ch] = plci->Id;
3885         plci->nl_req = 0;
3886       }
3887       else
3888       {
3889         /*
3890           Cancel return codes self, if feature was requested
3891           */
3892         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3893           a->FlowControlIdTable[ch] = 0;
3894           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3895             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3896             return;
3897           }
3898         }
3899 
3900         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3901         {
3902           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3903           if (ch == e->ReqCh)
3904             plci->nl_req = 0;
3905         }
3906         else
3907           plci->nl_req = 0;
3908       }
3909       if (plci->nl_req)
3910         control_rc (plci, 0, rc, ch, 0, true);
3911       else
3912       {
3913         if (req == N_XON)
3914         {
3915           channel_x_on (plci, ch);
3916           if (plci->internal_command)
3917             control_rc (plci, req, rc, ch, 0, true);
3918         }
3919         else
3920         {
3921           if (plci->nl_global_req)
3922           {
3923             global_req = plci->nl_global_req;
3924             plci->nl_global_req = 0;
3925             if (rc != ASSIGN_OK) {
3926               e->Id = 0;
3927               if (plci->rx_dma_descriptor > 0) {
3928                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3929                 plci->rx_dma_descriptor = 0;
3930               }
3931             }
3932             channel_xmit_xon (plci);
3933             control_rc (plci, 0, rc, ch, global_req, true);
3934           }
3935           else if (plci->data_sent)
3936           {
3937             channel_xmit_xon (plci);
3938             plci->data_sent = false;
3939             plci->NL.XNum = 1;
3940             data_rc (plci, ch);
3941             if (plci->internal_command)
3942               control_rc (plci, req, rc, ch, 0, true);
3943           }
3944           else
3945           {
3946             channel_xmit_xon (plci);
3947             control_rc (plci, req, rc, ch, 0, true);
3948           }
3949         }
3950       }
3951     }
3952     else
3953     {
3954       /*
3955          If REMOVE request was sent then we have to wait until
3956          return code with Id set to zero arrives.
3957          All other return codes should be ignored.
3958          */
3959       if (req == REMOVE)
3960       {
3961         if (e->Id)
3962         {
3963           dbug(1,dprintf("cancel RC in REMOVE state"));
3964           return;
3965         }
3966         plci->sig_remove_id = 0;
3967       }
3968       plci->sig_req = 0;
3969       if (plci->sig_global_req)
3970       {
3971         global_req = plci->sig_global_req;
3972         plci->sig_global_req = 0;
3973         if (rc != ASSIGN_OK)
3974           e->Id = 0;
3975         channel_xmit_xon (plci);
3976         control_rc (plci, 0, rc, ch, global_req, false);
3977       }
3978       else
3979       {
3980         channel_xmit_xon (plci);
3981         control_rc (plci, req, rc, ch, 0, false);
3982       }
3983     }
3984     /*
3985       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3986       same callback. Also if new XDI and protocol code used then jump
3987       direct to finish.
3988       */
3989     if (no_cancel_rc) {
3990       channel_xmit_xon(plci);
3991       goto capi_callback_suffix;
3992     }
3993   }
3994 
3995   channel_xmit_xon(plci);
3996 
3997   if (e->Ind) {
3998     if (e->user[0] &0x8000) {
3999       byte Ind = e->Ind & 0x0f;
4000       byte Ch = e->IndCh;
4001       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4002           (a->ch_flow_plci[Ch] == plci->Id)) {
4003         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4004           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4005         }
4006         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4007       }
4008       nl_ind(plci);
4009       if ((e->RNR != 1) &&
4010           (a->ch_flow_plci[Ch] == plci->Id) &&
4011           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4012         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4013         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4014       }
4015     } else {
4016       sig_ind(plci);
4017     }
4018     e->Ind = 0;
4019   }
4020 
4021 capi_callback_suffix:
4022 
4023   while (!plci->req_in
4024    && !plci->internal_command
4025    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4026   {
4027     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4028 
4029     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4030 
4031     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4032     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4033     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4034       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4035     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4036     {
4037       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4038       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4039     }
4040     else
4041     {
4042       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4043     }
4044     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4045     {
4046       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4047       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4048     }
4049     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4050     {
4051       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4052       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4053     }
4054     i = api_put (appl, m);
4055     if (i != 0)
4056     {
4057       if (m->header.command == _DATA_B3_R)
4058 
4059         TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4060 
4061       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4062       break;
4063     }
4064 
4065     if (plci->li_notify_update)
4066     {
4067       plci->li_notify_update = false;
4068       mixer_notify_update (plci, false);
4069     }
4070 
4071   }
4072   send_data(plci);
4073   send_req(plci);
4074 }
4075 
4076 
4077 void control_rc(PLCI   * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4078 {
4079   dword Id;
4080   dword rId;
4081   word Number;
4082   word Info=0;
4083   word i;
4084   word ncci;
4085   DIVA_CAPI_ADAPTER   * a;
4086   APPL   * appl;
4087   PLCI   * rplci;
4088     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4089     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4090 
4091   if (!plci) {
4092     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4093     return;
4094   }
4095   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4096   if(plci->req_in!=plci->req_out)
4097   {
4098     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4099     {
4100       dbug(1,dprintf("req_1return"));
4101       return;
4102     }
4103     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4104   }
4105   plci->req_in = plci->req_in_start = plci->req_out = 0;
4106   dbug(1,dprintf("control_rc"));
4107 
4108   appl = plci->appl;
4109   a = plci->adapter;
4110   ncci = a->ch_ncci[ch];
4111   if(appl)
4112   {
4113     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4114     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4115     Number = plci->number;
4116     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));
4117     dbug(1,dprintf("channels=0x%x",plci->channels));
4118     if (plci_remove_check(plci))
4119       return;
4120     if(req==REMOVE && rc==ASSIGN_OK)
4121     {
4122       sig_req(plci,HANGUP,0);
4123       sig_req(plci,REMOVE,0);
4124       send_req(plci);
4125     }
4126     if(plci->command)
4127     {
4128       switch(plci->command)
4129       {
4130       case C_HOLD_REQ:
4131         dbug(1,dprintf("HoldRC=0x%x",rc));
4132         SSparms[1] = (byte)S_HOLD;
4133         if(rc!=OK)
4134         {
4135           plci->SuppState = IDLE;
4136           Info = 0x2001;
4137         }
4138         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4139         break;
4140 
4141       case C_RETRIEVE_REQ:
4142         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4143         SSparms[1] = (byte)S_RETRIEVE;
4144         if(rc!=OK)
4145         {
4146           plci->SuppState = CALL_HELD;
4147           Info = 0x2001;
4148         }
4149         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4150         break;
4151 
4152       case _INFO_R:
4153         dbug(1,dprintf("InfoRC=0x%x",rc));
4154         if(rc!=OK) Info=_WRONG_STATE;
4155         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4156         break;
4157 
4158       case _CONNECT_R:
4159         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4160         if (plci->State == INC_DIS_PENDING)
4161           break;
4162         if(plci->Sig.Id!=0xff)
4163         {
4164           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4165            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4166           {
4167             dbug(1,dprintf("No more IDs/Call_Req failed"));
4168             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4169             plci_remove(plci);
4170             plci->State = IDLE;
4171             break;
4172           }
4173           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4174           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4175         }
4176         else /* D-ch activation */
4177         {
4178           if (rc != ASSIGN_OK)
4179           {
4180             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4181             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4182             plci_remove(plci);
4183             plci->State = IDLE;
4184             break;
4185           }
4186           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4187           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4188           plci->State = INC_ACT_PENDING;
4189         }
4190         break;
4191 
4192       case _CONNECT_I|RESPONSE:
4193         if (plci->State != INC_DIS_PENDING)
4194           plci->State = INC_CON_ACCEPT;
4195         break;
4196 
4197       case _DISCONNECT_R:
4198         if (plci->State == INC_DIS_PENDING)
4199           break;
4200         if(plci->Sig.Id!=0xff)
4201         {
4202           plci->State = OUTG_DIS_PENDING;
4203           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4204         }
4205         break;
4206 
4207       case SUSPEND_REQ:
4208         break;
4209 
4210       case RESUME_REQ:
4211         break;
4212 
4213       case _CONNECT_B3_R:
4214         if(rc!=OK)
4215         {
4216           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4217           break;
4218         }
4219         ncci = get_ncci (plci, ch, 0);
4220         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4221         plci->channels++;
4222         if(req==N_RESET)
4223         {
4224           a->ncci_state[ncci] = INC_ACT_PENDING;
4225           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4226           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4227         }
4228         else
4229         {
4230           a->ncci_state[ncci] = OUTG_CON_PENDING;
4231           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4232         }
4233         break;
4234 
4235       case _CONNECT_B3_I|RESPONSE:
4236         break;
4237 
4238       case _RESET_B3_R:
4239 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4240         break;
4241 
4242       case _DISCONNECT_B3_R:
4243         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4244         break;
4245 
4246       case _MANUFACTURER_R:
4247         break;
4248 
4249       case PERM_LIST_REQ:
4250         if(rc!=OK)
4251         {
4252           Info = _WRONG_IDENTIFIER;
4253           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4254           plci_remove(plci);
4255         }
4256         else
4257           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4258         break;
4259 
4260       default:
4261         break;
4262       }
4263       plci->command = 0;
4264     }
4265     else if (plci->internal_command)
4266     {
4267       switch(plci->internal_command)
4268       {
4269       case BLOCK_PLCI:
4270         return;
4271 
4272       case GET_MWI_STATE:
4273         if(rc==OK) /* command supported, wait for indication */
4274         {
4275           return;
4276         }
4277         plci_remove(plci);
4278         break;
4279 
4280         /* Get Supported Services */
4281       case GETSERV_REQ_PEND:
4282         if(rc==OK) /* command supported, wait for indication */
4283         {
4284           break;
4285         }
4286         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4287         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4288         plci_remove(plci);
4289         break;
4290 
4291       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4292       case INTERR_NUMBERS_REQ_PEND:
4293       case CF_START_PEND:                  /* Call Forwarding Start pending */
4294       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4295       case CCBS_REQUEST_REQ_PEND:
4296       case CCBS_DEACTIVATE_REQ_PEND:
4297       case CCBS_INTERROGATE_REQ_PEND:
4298         switch(plci->internal_command)
4299         {
4300           case INTERR_DIVERSION_REQ_PEND:
4301             SSparms[1] = S_INTERROGATE_DIVERSION;
4302             break;
4303           case INTERR_NUMBERS_REQ_PEND:
4304             SSparms[1] = S_INTERROGATE_NUMBERS;
4305             break;
4306           case CF_START_PEND:
4307             SSparms[1] = S_CALL_FORWARDING_START;
4308             break;
4309           case CF_STOP_PEND:
4310             SSparms[1] = S_CALL_FORWARDING_STOP;
4311             break;
4312           case CCBS_REQUEST_REQ_PEND:
4313             SSparms[1] = S_CCBS_REQUEST;
4314             break;
4315           case CCBS_DEACTIVATE_REQ_PEND:
4316             SSparms[1] = S_CCBS_DEACTIVATE;
4317             break;
4318           case CCBS_INTERROGATE_REQ_PEND:
4319             SSparms[1] = S_CCBS_INTERROGATE;
4320             break;
4321         }
4322         if(global_req==ASSIGN)
4323         {
4324           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4325           return;
4326         }
4327         if(!plci->appl) break;
4328         if(rc==ISDN_GUARD_REJ)
4329         {
4330           Info = _CAPI_GUARD_ERROR;
4331         }
4332         else if(rc!=OK)
4333         {
4334           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4335         }
4336         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4337               plci->number,"wws",Info,(word)3,SSparms);
4338         if(Info) plci_remove(plci);
4339         break;
4340 
4341         /* 3pty conference pending */
4342       case PTY_REQ_PEND:
4343         if(!plci->relatedPTYPLCI) break;
4344         rplci = plci->relatedPTYPLCI;
4345         SSparms[1] = plci->ptyState;
4346         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4347         if(rplci->tel) rId|=EXT_CONTROLLER;
4348         if(rc!=OK)
4349         {
4350           Info = 0x300E; /* not supported */
4351           plci->relatedPTYPLCI = NULL;
4352           plci->ptyState = 0;
4353         }
4354         sendf(rplci->appl,
4355               _FACILITY_R|CONFIRM,
4356               rId,
4357               plci->number,
4358               "wws",Info,(word)3,SSparms);
4359         break;
4360 
4361         /* Explicit Call Transfer pending */
4362       case ECT_REQ_PEND:
4363         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4364         if(!plci->relatedPTYPLCI) break;
4365         rplci = plci->relatedPTYPLCI;
4366         SSparms[1] = S_ECT;
4367         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4368         if(rplci->tel) rId|=EXT_CONTROLLER;
4369         if(rc!=OK)
4370         {
4371           Info = 0x300E; /* not supported */
4372           plci->relatedPTYPLCI = NULL;
4373           plci->ptyState = 0;
4374         }
4375         sendf(rplci->appl,
4376               _FACILITY_R|CONFIRM,
4377               rId,
4378               plci->number,
4379               "wws",Info,(word)3,SSparms);
4380         break;
4381 
4382       case _MANUFACTURER_R:
4383         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4384         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4385         {
4386           dbug(1,dprintf("No more IDs"));
4387           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4388           plci_remove(plci);  /* after codec init, internal codec commands pending */
4389         }
4390         break;
4391 
4392       case _CONNECT_R:
4393         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4394         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4395         {
4396           dbug(1,dprintf("No more IDs"));
4397           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4398           plci_remove(plci);  /* after codec init, internal codec commands pending */
4399         }
4400         break;
4401 
4402       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4403         return;
4404 
4405       case PERM_COD_CALL:
4406         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4407         plci->internal_command = PERM_COD_CONN_PEND;
4408         return;
4409 
4410       case PERM_COD_ASSIGN:
4411         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4412         if(rc!=ASSIGN_OK) break;
4413         sig_req(plci,CALL_REQ,0);
4414         send_req(plci);
4415         plci->internal_command = PERM_COD_CALL;
4416         return;
4417 
4418         /* Null Call Reference Request pending */
4419       case C_NCR_FAC_REQ:
4420         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4421         if(global_req==ASSIGN)
4422         {
4423           if(rc==ASSIGN_OK)
4424           {
4425             return;
4426           }
4427           else
4428           {
4429             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4430             appl->NullCREnable = false;
4431             plci_remove(plci);
4432           }
4433         }
4434         else if(req==NCR_FACILITY)
4435         {
4436           if(rc==OK)
4437           {
4438             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4439           }
4440           else
4441           {
4442             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4443             appl->NullCREnable = false;
4444           }
4445           plci_remove(plci);
4446         }
4447         break;
4448 
4449       case HOOK_ON_REQ:
4450         if(plci->channels)
4451         {
4452           if(a->ncci_state[ncci]==CONNECTED)
4453           {
4454             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4455             cleanup_ncci_data (plci, ncci);
4456             nl_req_ncci(plci,N_DISC,(byte)ncci);
4457           }
4458           break;
4459         }
4460         break;
4461 
4462       case HOOK_OFF_REQ:
4463         if (plci->State == INC_DIS_PENDING)
4464           break;
4465         sig_req(plci,CALL_REQ,0);
4466         send_req(plci);
4467         plci->State=OUTG_CON_PENDING;
4468         break;
4469 
4470 
4471       case MWI_ACTIVATE_REQ_PEND:
4472       case MWI_DEACTIVATE_REQ_PEND:
4473         if(global_req == ASSIGN && rc==ASSIGN_OK)
4474         {
4475           dbug(1,dprintf("MWI_REQ assigned"));
4476           return;
4477         }
4478         else if(rc!=OK)
4479         {                 
4480           if(rc==WRONG_IE)
4481           {
4482             Info = 0x2007; /* Illegal message parameter coding */
4483             dbug(1,dprintf("MWI_REQ invalid parameter"));
4484           }
4485           else
4486           {
4487             Info = 0x300B; /* not supported */                      
4488             dbug(1,dprintf("MWI_REQ not supported"));
4489           }
4490           /* 0x3010: Request not allowed in this state */
4491           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4492                     
4493         }
4494         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4495         {
4496           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4497         }
4498         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4499 
4500         if(plci->cr_enquiry)
4501         {
4502           sendf(plci->appl,
4503                 _FACILITY_R|CONFIRM,
4504                 Id&0xf,
4505                 plci->number,
4506                 "wws",Info,(word)3,SSparms);
4507           if(rc!=OK) plci_remove(plci);
4508         }
4509         else
4510         {
4511           sendf(plci->appl,
4512                 _FACILITY_R|CONFIRM,
4513                 Id,
4514                 plci->number,
4515                 "wws",Info,(word)3,SSparms);
4516         }
4517         break;
4518 
4519       case CONF_BEGIN_REQ_PEND:
4520       case CONF_ADD_REQ_PEND:
4521       case CONF_SPLIT_REQ_PEND:
4522       case CONF_DROP_REQ_PEND:
4523       case CONF_ISOLATE_REQ_PEND:
4524       case CONF_REATTACH_REQ_PEND:
4525         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4526         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4527         rplci = plci;
4528         rId = Id;
4529         switch(plci->internal_command)
4530         {
4531           case CONF_BEGIN_REQ_PEND:
4532             SSparms[1] = S_CONF_BEGIN;
4533             break;
4534           case CONF_ADD_REQ_PEND:
4535             SSparms[1] = S_CONF_ADD;
4536             rplci = plci->relatedPTYPLCI;
4537             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4538             break;
4539           case CONF_SPLIT_REQ_PEND:
4540             SSparms[1] = S_CONF_SPLIT;
4541             break;
4542           case CONF_DROP_REQ_PEND:
4543             SSparms[1] = S_CONF_DROP;
4544             break;
4545           case CONF_ISOLATE_REQ_PEND:
4546             SSparms[1] = S_CONF_ISOLATE;
4547             break;
4548           case CONF_REATTACH_REQ_PEND:
4549             SSparms[1] = S_CONF_REATTACH;
4550             break;
4551         }
4552         
4553         if(rc!=OK)
4554         {
4555           Info = 0x300E; /* not supported */
4556           plci->relatedPTYPLCI = NULL;
4557           plci->ptyState = 0;
4558         }
4559         sendf(rplci->appl,
4560               _FACILITY_R|CONFIRM,
4561               rId,
4562               plci->number,
4563               "wws",Info,(word)3,SSparms);
4564         break;
4565 
4566       case VSWITCH_REQ_PEND:
4567         if(rc!=OK)
4568         {
4569           if(plci->relatedPTYPLCI)
4570           {
4571             plci->relatedPTYPLCI->vswitchstate=0;
4572             plci->relatedPTYPLCI->vsprot=0;
4573             plci->relatedPTYPLCI->vsprotdialect=0;    
4574           }
4575           plci->vswitchstate=0;
4576           plci->vsprot=0;
4577           plci->vsprotdialect=0;
4578         }
4579         else
4580         {
4581           if(plci->relatedPTYPLCI &&
4582              plci->vswitchstate==1 &&
4583              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4584             plci->vswitchstate=3;
4585         }
4586         break;
4587 
4588   /* Call Deflection Request pending (SSCT) */
4589       case CD_REQ_PEND:
4590         SSparms[1] = S_CALL_DEFLECTION;
4591         if(rc!=OK)
4592         {
4593           Info = 0x300E; /* not supported */
4594           plci->appl->CDEnable = 0;
4595         }  
4596         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4597           plci->number,"wws",Info,(word)3,SSparms);
4598         break;
4599 
4600       case RTP_CONNECT_B3_REQ_COMMAND_2:
4601         if (rc == OK)
4602         {
4603           ncci = get_ncci (plci, ch, 0);
4604           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4605           plci->channels++;
4606           a->ncci_state[ncci] = OUTG_CON_PENDING;
4607         }
4608 
4609       default:
4610         if (plci->internal_command_queue[0])
4611         {
4612           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4613           if (plci->internal_command)
4614             return;
4615         }
4616         break;
4617       }
4618       next_internal_command (Id, plci);
4619     }
4620   }
4621   else /* appl==0 */
4622   {
4623     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4624     if(plci->tel) Id|=EXT_CONTROLLER;
4625 
4626     switch(plci->internal_command)
4627     {
4628     case BLOCK_PLCI:
4629       return;
4630 
4631     case START_L1_SIG_ASSIGN_PEND:
4632     case REM_L1_SIG_ASSIGN_PEND:
4633       if(global_req == ASSIGN)
4634       {
4635         break;
4636       }
4637       else
4638       {
4639         dbug(1,dprintf("***L1 Req rem PLCI"));
4640         plci->internal_command = 0;
4641         sig_req(plci,REMOVE,0);
4642         send_req(plci);
4643       }
4644       break;
4645 
4646       /* Call Deflection Request pending, just no appl ptr assigned */
4647     case CD_REQ_PEND:
4648       SSparms[1] = S_CALL_DEFLECTION;
4649       if(rc!=OK)
4650       {
4651         Info = 0x300E; /* not supported */
4652       }
4653       for(i=0; i<max_appl; i++)
4654       {
4655         if(application[i].CDEnable)
4656         {
4657           if(!application[i].Id) application[i].CDEnable = 0;
4658           else
4659           {
4660             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4661                   plci->number,"wws",Info,(word)3,SSparms);
4662             if(Info) application[i].CDEnable = 0;
4663           }
4664         }
4665       }
4666       plci->internal_command = 0;
4667       break;
4668 
4669     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4670       return;
4671 
4672     case PERM_COD_CALL:
4673       plci->internal_command = PERM_COD_CONN_PEND;
4674       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4675       return;
4676 
4677     case PERM_COD_ASSIGN:
4678       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4679       plci->internal_command = 0;
4680       if(rc!=ASSIGN_OK) break;
4681       plci->internal_command = PERM_COD_CALL;
4682       sig_req(plci,CALL_REQ,0);
4683       send_req(plci);
4684       return;
4685 
4686     case LISTEN_SIG_ASSIGN_PEND:
4687       if(rc == ASSIGN_OK)
4688       {
4689         plci->internal_command = 0;
4690         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4691         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4692         sig_req(plci,INDICATE_REQ,0);
4693         send_req(plci);
4694       }
4695       else
4696       {
4697         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4698         a->listen_active--;
4699         plci_remove(plci);
4700         plci->State = IDLE;
4701       }
4702       break;
4703 
4704     case USELAW_REQ:
4705       if(global_req == ASSIGN)
4706       {
4707         if (rc==ASSIGN_OK)
4708       {
4709         sig_req(plci,LAW_REQ,0);
4710         send_req(plci);
4711         dbug(1,dprintf("Auto-Law assigned"));
4712         }
4713         else
4714         {
4715           dbug(1,dprintf("Auto-Law assign failed"));
4716           a->automatic_law = 3;
4717           plci->internal_command = 0;
4718           a->automatic_lawPLCI = NULL;
4719         }
4720         break;
4721       }
4722       else if(req == LAW_REQ && rc==OK)
4723       {
4724         dbug(1,dprintf("Auto-Law initiated"));
4725         a->automatic_law = 2;
4726         plci->internal_command = 0;
4727       }
4728       else
4729       {
4730         dbug(1,dprintf("Auto-Law not supported"));
4731         a->automatic_law = 3;
4732         plci->internal_command = 0;
4733         sig_req(plci,REMOVE,0);
4734         send_req(plci);
4735         a->automatic_lawPLCI = NULL;
4736       }
4737       break;
4738     }
4739     plci_remove_check(plci);
4740   }
4741 }
4742 
4743 void data_rc(PLCI   * plci, byte ch)
4744 {
4745   dword Id;
4746   DIVA_CAPI_ADAPTER   * a;
4747   NCCI   *ncci_ptr;
4748   DATA_B3_DESC   *data;
4749   word ncci;
4750 
4751   if (plci->appl)
4752   {
4753     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4754     a = plci->adapter;
4755     ncci = a->ch_ncci[ch];
4756     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4757     {
4758       ncci_ptr = &(a->ncci[ncci]);
4759       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4760       if (ncci_ptr->data_pending)
4761       {
4762         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4763         if (!(data->Flags &4) && a->ncci_state[ncci])
4764         {
4765           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4766           if(plci->tel) Id|=EXT_CONTROLLER;
4767           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4768                 "ww",data->Handle,0);
4769         }
4770         (ncci_ptr->data_out)++;
4771         if (ncci_ptr->data_out == MAX_DATA_B3)
4772           ncci_ptr->data_out = 0;
4773         (ncci_ptr->data_pending)--;
4774       }
4775     }
4776   }
4777 }
4778 
4779 void data_ack(PLCI   * plci, byte ch)
4780 {
4781   dword Id;
4782   DIVA_CAPI_ADAPTER   * a;
4783   NCCI   *ncci_ptr;
4784   word ncci;
4785 
4786   a = plci->adapter;
4787   ncci = a->ch_ncci[ch];
4788   ncci_ptr = &(a->ncci[ncci]);
4789   if (ncci_ptr->data_ack_pending)
4790   {
4791     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4792     {
4793       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4794       if(plci->tel) Id|=EXT_CONTROLLER;
4795       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4796             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4797     }
4798     (ncci_ptr->data_ack_out)++;
4799     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4800       ncci_ptr->data_ack_out = 0;
4801     (ncci_ptr->data_ack_pending)--;
4802   }
4803 }
4804 
4805 void sig_ind(PLCI   * plci)
4806 {
4807   dword x_Id;
4808   dword Id;
4809   dword rId;
4810   word Number = 0;
4811   word i;
4812   word cip;
4813   dword cip_mask;
4814   byte   *ie;
4815   DIVA_CAPI_ADAPTER   * a;
4816     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4817 #define MAXPARMSIDS 31
4818     byte   * parms[MAXPARMSIDS];
4819     byte   * add_i[4];
4820     byte   * multi_fac_parms[MAX_MULTI_IE];
4821     byte   * multi_pi_parms [MAX_MULTI_IE];
4822     byte   * multi_ssext_parms [MAX_MULTI_IE];
4823     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4824 
4825     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4826 
4827   byte ai_len;
4828     byte   *esc_chi = "";
4829     byte   *esc_law = "";
4830     byte   *pty_cai = "";
4831     byte   *esc_cr  = "";
4832     byte   *esc_profile = "";
4833 
4834     byte facility[256];
4835   PLCI   * tplci = NULL;
4836   byte chi[] = "\x02\x18\x01";
4837   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4838     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4839   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4840   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4841   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4842   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4843     word parms_id[] =
4844          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4845           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4846           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4847           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4848           /* 14 FTY repl by ESC_CHI */
4849           /* 18 PI  repl by ESC_LAW */
4850          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4851      word multi_fac_id[] = {1, FTY};
4852      word multi_pi_id[]  = {1, PI};
4853      word multi_CiPN_id[]  = {1, OAD};
4854      word multi_ssext_id[]  = {1, ESC_SSEXT};
4855 
4856      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4857 
4858   byte   * cau;
4859   word ncci;
4860     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4861     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4862     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4863     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4864   byte force_mt_info = false;
4865   byte dir;
4866   dword d;
4867   word w;
4868 
4869   a = plci->adapter;
4870   Id = ((word)plci->Id<<8)|a->Id;
4871   PUT_WORD(&SS_Ind[4],0x0000);
4872 
4873   if (plci->sig_remove_id)
4874   {
4875     plci->Sig.RNR = 2; /* discard */
4876     dbug(1,dprintf("SIG discard while remove pending"));
4877     return;
4878   }
4879   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4880   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4881     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4882   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4883   {
4884     plci->Sig.RNR = 1;
4885     return;
4886   }
4887   if(plci->Sig.Ind==HANGUP && plci->channels)
4888   {
4889     plci->Sig.RNR = 1;
4890     plci->hangup_flow_ctrl_timer++;
4891     /* recover the network layer after timeout */
4892     if(plci->hangup_flow_ctrl_timer==100)
4893     {
4894       dbug(1,dprintf("Exceptional disc"));
4895       plci->Sig.RNR = 0;
4896       plci->hangup_flow_ctrl_timer = 0;
4897       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4898       {
4899         if (a->ncci_plci[ncci] == plci->Id)
4900         {
4901           cleanup_ncci_data (plci, ncci);
4902           if(plci->channels)plci->channels--;
4903           if (plci->appl)
4904             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4905         }
4906       }
4907       if (plci->appl)
4908         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4909       plci_remove(plci);
4910       plci->State=IDLE;
4911     }
4912     return;
4913   }
4914 
4915   /* do first parse the info with no OAD in, because OAD will be converted */
4916   /* first the multiple facility IE, then mult. progress ind.              */
4917   /* then the parameters for the info_ind + conn_ind                       */
4918   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4919   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4920   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4921 
4922   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4923 
4924   IndParse(plci,parms_id,parms,0);
4925   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4926   esc_chi  = parms[14];
4927   esc_law  = parms[18];
4928   pty_cai  = parms[24];
4929   esc_cr   = parms[25];
4930   esc_profile = parms[27];
4931   if(esc_cr[0] && plci)
4932   {
4933     if(plci->cr_enquiry && plci->appl)
4934     {
4935       plci->cr_enquiry = false;
4936       /* d = MANU_ID            */
4937       /* w = m_command          */
4938       /* b = total length       */
4939       /* b = indication type    */
4940       /* b = length of all IEs  */
4941       /* b = IE1                */
4942       /* S = IE1 length + cont. */
4943       /* b = IE2                */
4944       /* S = IE2 length + cont. */
4945       sendf(plci->appl,
4946         _MANUFACTURER_I,
4947         Id,
4948         0,
4949         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4950         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);
4951     }
4952   }
4953   /* create the additional info structure                                  */
4954   add_i[1] = parms[15]; /* KEY of additional info */
4955   add_i[2] = parms[11]; /* UUI of additional info */
4956   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4957 
4958   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4959   /* indication returns by the card if requested by the function           */
4960   /* AutomaticLaw() after driver init                                      */
4961   if (a->automatic_law<4)
4962   {
4963     if(esc_law[0]){
4964       if(esc_law[2]){
4965         dbug(0,dprintf("u-Law selected"));
4966         a->u_law = 1;
4967       }
4968       else {
4969         dbug(0,dprintf("a-Law selected"));
4970         a->u_law = 0;
4971       }
4972       a->automatic_law = 4;
4973       if(plci==a->automatic_lawPLCI) {
4974         plci->internal_command = 0;
4975         sig_req(plci,REMOVE,0);
4976         send_req(plci);
4977         a->automatic_lawPLCI = NULL;
4978       }
4979     }
4980     if (esc_profile[0])
4981     {
4982       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4983         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4984         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4985         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4986 
4987       a->profile.Global_Options &= 0x000000ffL;
4988       a->profile.B1_Protocols &= 0x000003ffL;
4989       a->profile.B2_Protocols &= 0x00001fdfL;
4990       a->profile.B3_Protocols &= 0x000000b7L;
4991 
4992       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4993         GL_BCHANNEL_OPERATION_SUPPORTED;
4994       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4995       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4996       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4997       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4998       a->man_profile.private_options = 0;
4999 
5000       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5001       {
5002         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5003         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5004       }
5005 
5006 
5007       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5008         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5009       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5010       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5011 
5012 
5013       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5014         a->man_profile.private_options |= 1L << PRIVATE_T38;
5015 
5016 
5017       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5018         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5019 
5020 
5021       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5022         a->man_profile.private_options |= 1L << PRIVATE_V18;
5023 
5024 
5025       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5026         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5027 
5028 
5029       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5030         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5031 
5032 
5033       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5034         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5035 
5036 
5037       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5038         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5039 
5040 
5041       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5042         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5043 
5044     }
5045     else
5046     {
5047       a->profile.Global_Options &= 0x0000007fL;
5048       a->profile.B1_Protocols &= 0x000003dfL;
5049       a->profile.B2_Protocols &= 0x00001adfL;
5050       a->profile.B3_Protocols &= 0x000000b7L;
5051       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5052     }
5053     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5054       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5055     {
5056       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5057     }
5058     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5059     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5060       UnMapController (a->Id), a->profile.Global_Options,
5061       a->profile.B1_Protocols, a->profile.B2_Protocols,
5062       a->profile.B3_Protocols, a->manufacturer_features));
5063   }
5064   /* codec plci for the handset/hook state support is just an internal id  */
5065   if(plci!=a->AdvCodecPLCI)
5066   {
5067     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5068     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5069     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5070     SendInfo(plci,Id, parms, force_mt_info);
5071 
5072     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5073 
5074   }
5075 
5076   /* switch the codec to the b-channel                                     */
5077   if(esc_chi[0] && plci && !plci->SuppState){
5078     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5079     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5080     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5081     if(plci->tel==ADV_VOICE && plci->appl) {
5082       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5083     }
5084   }
5085 
5086   if(plci->appl) Number = plci->appl->Number++;
5087 
5088   switch(plci->Sig.Ind) {
5089   /* Response to Get_Supported_Services request */
5090   case S_SUPPORTED:
5091     dbug(1,dprintf("S_Supported"));
5092     if(!plci->appl) break;
5093     if(pty_cai[0]==4)
5094     {
5095       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5096     }
5097     else
5098     {
5099       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5100     }
5101     PUT_WORD (&CF_Ind[1], 0);
5102     PUT_WORD (&CF_Ind[4], 0);
5103     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5104     plci_remove(plci);
5105     break;
5106                     
5107   /* Supplementary Service rejected */
5108   case S_SERVICE_REJ:
5109     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5110     if(!pty_cai[0]) break;
5111     switch (pty_cai[5])
5112     {
5113     case ECT_EXECUTE:
5114     case THREE_PTY_END:
5115     case THREE_PTY_BEGIN:
5116       if(!plci->relatedPTYPLCI) break;
5117       tplci = plci->relatedPTYPLCI;
5118       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5119       if(tplci->tel) rId|=EXT_CONTROLLER;
5120       if(pty_cai[5]==ECT_EXECUTE)
5121       {
5122         PUT_WORD(&SS_Ind[1],S_ECT);
5123 
5124         plci->vswitchstate=0;
5125         plci->relatedPTYPLCI->vswitchstate=0;
5126 
5127       }
5128       else
5129       {
5130         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5131       }
5132       if(pty_cai[2]!=0xff)
5133       {
5134         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5135       }
5136       else
5137       {
5138         PUT_WORD(&SS_Ind[4],0x300E);
5139       }
5140       plci->relatedPTYPLCI = NULL;
5141       plci->ptyState = 0;
5142       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5143       break;
5144 
5145     case CALL_DEFLECTION:
5146       if(pty_cai[2]!=0xff)
5147       {
5148         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5149       }
5150       else
5151       {
5152         PUT_WORD(&SS_Ind[4],0x300E);
5153       }
5154       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5155       for(i=0; i<max_appl; i++)
5156       {
5157         if(application[i].CDEnable)
5158         {
5159           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5160           application[i].CDEnable = false;
5161         }
5162       }
5163       break;
5164 
5165     case DEACTIVATION_DIVERSION:
5166     case ACTIVATION_DIVERSION:
5167     case DIVERSION_INTERROGATE_CFU:
5168     case DIVERSION_INTERROGATE_CFB:
5169     case DIVERSION_INTERROGATE_CFNR:
5170     case DIVERSION_INTERROGATE_NUM:
5171     case CCBS_REQUEST:
5172     case CCBS_DEACTIVATE:
5173     case CCBS_INTERROGATE:
5174       if(!plci->appl) break;
5175       if(pty_cai[2]!=0xff)
5176       {
5177         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5178       }
5179       else
5180       {
5181         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5182       }
5183       switch (pty_cai[5])
5184       {
5185         case DEACTIVATION_DIVERSION:
5186           dbug(1,dprintf("Deact_Div"));
5187           Interr_Err_Ind[0]=0x9;
5188           Interr_Err_Ind[3]=0x6;
5189           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5190           break;
5191         case ACTIVATION_DIVERSION:
5192           dbug(1,dprintf("Act_Div"));
5193           Interr_Err_Ind[0]=0x9;
5194           Interr_Err_Ind[3]=0x6;
5195           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5196           break;
5197         case DIVERSION_INTERROGATE_CFU:
5198         case DIVERSION_INTERROGATE_CFB:
5199         case DIVERSION_INTERROGATE_CFNR:
5200           dbug(1,dprintf("Interr_Div"));
5201           Interr_Err_Ind[0]=0xa;
5202           Interr_Err_Ind[3]=0x7;
5203           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5204           break;
5205         case DIVERSION_INTERROGATE_NUM:
5206           dbug(1,dprintf("Interr_Num"));
5207           Interr_Err_Ind[0]=0xa;
5208           Interr_Err_Ind[3]=0x7;
5209           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5210           break;
5211         case CCBS_REQUEST:
5212           dbug(1,dprintf("CCBS Request"));
5213           Interr_Err_Ind[0]=0xd;
5214           Interr_Err_Ind[3]=0xa;
5215           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5216           break;
5217         case CCBS_DEACTIVATE:
5218           dbug(1,dprintf("CCBS Deactivate"));
5219           Interr_Err_Ind[0]=0x9;
5220           Interr_Err_Ind[3]=0x6;
5221           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5222           break;
5223         case CCBS_INTERROGATE:
5224           dbug(1,dprintf("CCBS Interrogate"));
5225           Interr_Err_Ind[0]=0xb;
5226           Interr_Err_Ind[3]=0x8;
5227           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5228           break;
5229       }
5230       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5231       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5232       plci_remove(plci);
5233       break;
5234     case ACTIVATION_MWI:      
5235     case DEACTIVATION_MWI:
5236       if(pty_cai[5]==ACTIVATION_MWI)
5237       {
5238         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5239       }
5240       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5241       
5242       if(pty_cai[2]!=0xff)
5243       {
5244         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5245       }
5246       else
5247       {
5248         PUT_WORD(&SS_Ind[4],0x300E);
5249       }
5250 
5251       if(plci->cr_enquiry)
5252       {
5253         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5254         plci_remove(plci);
5255       }
5256       else
5257       {
5258         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5259       }
5260       break;
5261     case CONF_ADD: /* ERROR */
5262     case CONF_BEGIN:
5263     case CONF_DROP:
5264     case CONF_ISOLATE:
5265     case CONF_REATTACH:
5266       CONF_Ind[0]=9;
5267       CONF_Ind[3]=6;   
5268       switch(pty_cai[5])
5269       {
5270       case CONF_BEGIN:
5271           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5272           plci->ptyState = 0;
5273           break;
5274       case CONF_DROP:
5275           CONF_Ind[0]=5;
5276           CONF_Ind[3]=2;
5277           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5278           plci->ptyState = CONNECTED;
5279           break;
5280       case CONF_ISOLATE:
5281           CONF_Ind[0]=5;
5282           CONF_Ind[3]=2;
5283           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5284           plci->ptyState = CONNECTED;
5285           break;
5286       case CONF_REATTACH:
5287           CONF_Ind[0]=5;
5288           CONF_Ind[3]=2;
5289           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5290           plci->ptyState = CONNECTED;
5291           break;
5292       case CONF_ADD:
5293           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5294           plci->relatedPTYPLCI = NULL;
5295           tplci=plci->relatedPTYPLCI;
5296           if(tplci) tplci->ptyState = CONNECTED;
5297           plci->ptyState = CONNECTED;
5298           break;
5299       }
5300           
5301       if(pty_cai[2]!=0xff)
5302       {
5303         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5304       }
5305       else
5306       {
5307         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5308                                             within the required time */
5309       }
5310 
5311       PUT_DWORD(&CONF_Ind[6],0x0);
5312       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5313       break;
5314     }
5315     break;
5316 
5317   /* Supplementary Service indicates success */
5318   case S_SERVICE:
5319     dbug(1,dprintf("Service_Ind"));
5320     PUT_WORD (&CF_Ind[4], 0);
5321     switch (pty_cai[5])
5322     {
5323     case THREE_PTY_END:
5324     case THREE_PTY_BEGIN:
5325     case ECT_EXECUTE:
5326       if(!plci->relatedPTYPLCI) break;
5327       tplci = plci->relatedPTYPLCI;
5328       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5329       if(tplci->tel) rId|=EXT_CONTROLLER;
5330       if(pty_cai[5]==ECT_EXECUTE)
5331       {
5332         PUT_WORD(&SS_Ind[1],S_ECT);
5333 
5334         if(plci->vswitchstate!=3)
5335         {
5336 
5337         plci->ptyState = IDLE;
5338         plci->relatedPTYPLCI = NULL;
5339         plci->ptyState = 0;
5340 
5341         }
5342 
5343         dbug(1,dprintf("ECT OK"));
5344         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5345 
5346 
5347 
5348       }
5349       else
5350       {
5351         switch (plci->ptyState)
5352         {
5353         case S_3PTY_BEGIN:
5354           plci->ptyState = CONNECTED;
5355           dbug(1,dprintf("3PTY ON"));
5356           break;
5357 
5358         case S_3PTY_END:
5359           plci->ptyState = IDLE;
5360           plci->relatedPTYPLCI = NULL;
5361           plci->ptyState = 0;
5362           dbug(1,dprintf("3PTY OFF"));
5363           break;
5364         }
5365         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5366         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5367       }
5368       break;
5369 
5370     case CALL_DEFLECTION:
5371       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5372       for(i=0; i<max_appl; i++)
5373       {
5374         if(application[i].CDEnable)
5375         {
5376           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5377           application[i].CDEnable = false;
5378         }
5379       }
5380       break;
5381 
5382     case DEACTIVATION_DIVERSION:
5383     case ACTIVATION_DIVERSION:
5384       if(!plci->appl) break;
5385       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5386       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5387       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5388       plci_remove(plci);
5389       break;
5390 
5391     case DIVERSION_INTERROGATE_CFU:
5392     case DIVERSION_INTERROGATE_CFB:
5393     case DIVERSION_INTERROGATE_CFNR:
5394     case DIVERSION_INTERROGATE_NUM:
5395     case CCBS_REQUEST:
5396     case CCBS_DEACTIVATE:
5397     case CCBS_INTERROGATE:
5398       if(!plci->appl) break;
5399       switch (pty_cai[5])
5400       {
5401         case DIVERSION_INTERROGATE_CFU:
5402         case DIVERSION_INTERROGATE_CFB:
5403         case DIVERSION_INTERROGATE_CFNR:
5404           dbug(1,dprintf("Interr_Div"));
5405           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5406           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5407           break;
5408         case DIVERSION_INTERROGATE_NUM:
5409           dbug(1,dprintf("Interr_Num"));
5410           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5411           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5412           break;
5413         case CCBS_REQUEST:
5414           dbug(1,dprintf("CCBS Request"));
5415           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5416           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5417           break;
5418         case CCBS_DEACTIVATE:
5419           dbug(1,dprintf("CCBS Deactivate"));
5420           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5421           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5422           break;
5423         case CCBS_INTERROGATE:
5424           dbug(1,dprintf("CCBS Interrogate"));
5425           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5426           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5427           break;
5428       }
5429       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5430       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5431       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5432       plci_remove(plci);
5433       break;
5434 
5435     case ACTIVATION_MWI:
5436     case DEACTIVATION_MWI:
5437       if(pty_cai[5]==ACTIVATION_MWI)
5438       {
5439         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5440       }
5441       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5442       if(plci->cr_enquiry)
5443       {
5444         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5445         plci_remove(plci);
5446       }
5447       else
5448       {
5449         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5450       }
5451       break;
5452     case MWI_INDICATION:
5453       if(pty_cai[0]>=0x12)
5454       {
5455         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5456         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5457         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5458         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5459         {
5460           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5461           {
5462             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5463             plci_remove(plci);
5464             return;
5465           }
5466           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5467           pty_cai[0]=0;
5468         }
5469         else
5470         {
5471           for(i=0; i<max_appl; i++)
5472           {                     
5473             if(a->Notification_Mask[i]&SMASK_MWI)
5474             {
5475               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5476               pty_cai[0]=0;
5477             }
5478           }
5479         }
5480 
5481         if(!pty_cai[0])
5482         { /* acknowledge */
5483           facility[2]= 0; /* returncode */
5484         }
5485         else facility[2]= 0xff;
5486       }
5487       else
5488       {
5489         /* reject */
5490         facility[2]= 0xff; /* returncode */
5491       }
5492       facility[0]= 2;
5493       facility[1]= MWI_RESPONSE; /* Function */
5494       add_p(plci,CAI,facility);
5495       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5496       sig_req(plci,S_SERVICE,0);
5497       send_req(plci);
5498       plci->command = 0;
5499       next_internal_command (Id, plci);
5500       break;
5501     case CONF_ADD: /* OK */
5502     case CONF_BEGIN:
5503     case CONF_DROP:
5504     case CONF_ISOLATE:
5505     case CONF_REATTACH:
5506     case CONF_PARTYDISC:
5507       CONF_Ind[0]=9;
5508       CONF_Ind[3]=6;
5509       switch(pty_cai[5])
5510       {
5511       case CONF_BEGIN:
5512           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5513           if(pty_cai[0]==6)
5514           {
5515               d=pty_cai[6];
5516               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5517           }
5518           else
5519           {
5520               PUT_DWORD(&CONF_Ind[6],0x0);
5521           }
5522           break;
5523       case CONF_ISOLATE:
5524           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5525           CONF_Ind[0]=5;
5526           CONF_Ind[3]=2;
5527           break;
5528       case CONF_REATTACH:
5529           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5530           CONF_Ind[0]=5;
5531           CONF_Ind[3]=2;
5532           break;
5533       case CONF_DROP:
5534           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5535           CONF_Ind[0]=5;
5536           CONF_Ind[3]=2;
5537           break;
5538       case CONF_ADD:
5539           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5540           d=pty_cai[6];
5541           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5542           tplci=plci->relatedPTYPLCI;
5543           if(tplci) tplci->ptyState = CONNECTED;
5544           break;
5545       case CONF_PARTYDISC:
5546           CONF_Ind[0]=7;
5547           CONF_Ind[3]=4;          
5548           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5549           d=pty_cai[6];
5550           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5551           break;
5552       }
5553       plci->ptyState = CONNECTED;
5554       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5555       break;
5556     case CCBS_INFO_RETAIN:
5557     case CCBS_ERASECALLLINKAGEID:
5558     case CCBS_STOP_ALERTING:
5559       CONF_Ind[0]=5;
5560       CONF_Ind[3]=2;
5561       switch(pty_cai[5])
5562       {
5563       case CCBS_INFO_RETAIN:
5564         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5565         break;
5566       case CCBS_STOP_ALERTING:
5567         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5568     break;
5569       case CCBS_ERASECALLLINKAGEID:
5570         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5571         CONF_Ind[0]=7;
5572         CONF_Ind[3]=4;
5573         CONF_Ind[6]=0;
5574         CONF_Ind[7]=0;
5575         break;
5576       }      
5577       w=pty_cai[6];
5578       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5579 
5580       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5581       {
5582         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5583       }
5584       else
5585       {
5586         for(i=0; i<max_appl; i++)
5587             if(a->Notification_Mask[i]&SMASK_CCBS)
5588                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5589       }
5590       break;
5591     }
5592     break;
5593   case CALL_HOLD_REJ:
5594     cau = parms[7];
5595     if(cau)
5596     {
5597       i = _L3_CAUSE | cau[2];
5598       if(cau[2]==0) i = 0x3603;
5599     }
5600     else
5601     {
5602       i = 0x3603;
5603     }
5604     PUT_WORD(&SS_Ind[1],S_HOLD);
5605     PUT_WORD(&SS_Ind[4],i);
5606     if(plci->SuppState == HOLD_REQUEST)
5607     {
5608       plci->SuppState = IDLE;
5609       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5610     }
5611     break;
5612 
5613   case CALL_HOLD_ACK:
5614     if(plci->SuppState == HOLD_REQUEST)
5615     {
5616       plci->SuppState = CALL_HELD;
5617       CodecIdCheck(a, plci);
5618       start_internal_command (Id, plci, hold_save_command);
5619     }
5620     break;
5621 
5622   case CALL_RETRIEVE_REJ:
5623     cau = parms[7];
5624     if(cau)
5625     {
5626       i = _L3_CAUSE | cau[2];
5627       if(cau[2]==0) i = 0x3603;
5628     }
5629     else
5630     {
5631       i = 0x3603;
5632     }
5633     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5634     PUT_WORD(&SS_Ind[4],i);
5635     if(plci->SuppState == RETRIEVE_REQUEST)
5636     {
5637       plci->SuppState = CALL_HELD;
5638       CodecIdCheck(a, plci);
5639       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5640     }
5641     break;
5642 
5643   case CALL_RETRIEVE_ACK:
5644     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5645     if(plci->SuppState == RETRIEVE_REQUEST)
5646     {
5647       plci->SuppState = IDLE;
5648       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5649       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5650       if(plci->tel)
5651       {
5652         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5653         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5654         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5655         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5656         {
5657           dbug(1,dprintf("Get B-ch"));
5658           start_internal_command (Id, plci, retrieve_restore_command);
5659         }
5660         else
5661           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5662       }
5663       else
5664         start_internal_command (Id, plci, retrieve_restore_command);
5665     }
5666     break;
5667 
5668   case INDICATE_IND:
5669     if(plci->State != LISTENING) {
5670       sig_req(plci,HANGUP,0);
5671       send_req(plci);
5672       break;
5673     }
5674     cip = find_cip(a,parms[4],parms[6]);
5675     cip_mask = 1L<<cip;
5676     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5677     clear_c_ind_mask (plci);
5678     if (!remove_started && !a->adapter_disabled)
5679     {
5680       set_c_ind_mask_bit (plci, MAX_APPL);
5681       group_optimization(a, plci);
5682       for(i=0; i<max_appl; i++) {
5683         if(application[i].Id
5684         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5685         && CPN_filter_ok(parms[0],a,i)
5686         && test_group_ind_mask_bit (plci, i) ) {
5687           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5688           set_c_ind_mask_bit (plci, i);
5689           dump_c_ind_mask (plci);
5690           plci->State = INC_CON_PENDING;
5691           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5692             CALL_DIR_IN | CALL_DIR_ANSWER;
5693           if(esc_chi[0]) {
5694             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5695             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5696           }
5697           /* if a listen on the ext controller is done, check if hook states */
5698           /* are supported or if just a on board codec must be activated     */
5699           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5700             if(a->profile.Global_Options & HANDSET)
5701               plci->tel = ADV_VOICE;
5702             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5703               plci->tel = CODEC;
5704             if(plci->tel) Id|=EXT_CONTROLLER;
5705             a->codec_listen[i] = plci;
5706           }
5707 
5708           sendf(&application[i],_CONNECT_I,Id,0,
5709                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5710                              parms[0],    /* CalledPartyNumber   */
5711                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5712                              parms[2],    /* CalledPartySubad    */
5713                              parms[3],    /* CallingPartySubad   */
5714                              parms[4],    /* BearerCapability    */
5715                              parms[5],    /* LowLC               */
5716                              parms[6],    /* HighLC              */
5717                              ai_len,      /* nested struct add_i */
5718                              add_i[0],    /* B channel info    */
5719                              add_i[1],    /* keypad facility   */
5720                              add_i[2],    /* user user data    */
5721                              add_i[3],    /* nested facility   */
5722                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5723                              );
5724           SendSSExtInd(&application[i],
5725                         plci,
5726                         Id,
5727                         multi_ssext_parms);
5728           SendSetupInfo(&application[i],
5729                         plci,
5730                         Id,
5731                         parms,
5732                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5733         }
5734       }
5735       clear_c_ind_mask_bit (plci, MAX_APPL);
5736       dump_c_ind_mask (plci);
5737     }
5738     if(c_ind_mask_empty (plci)) {
5739       sig_req(plci,HANGUP,0);
5740       send_req(plci);
5741       plci->State = IDLE;
5742     }
5743     plci->notifiedcall = 0;
5744     a->listen_active--;
5745     listen_check(a);
5746     break;
5747 
5748   case CALL_PEND_NOTIFY:
5749     plci->notifiedcall = 1;
5750     listen_check(a);
5751     break;
5752 
5753   case CALL_IND:
5754   case CALL_CON:
5755     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5756     {
5757       if(plci->internal_command==PERM_COD_CONN_PEND)
5758       {
5759         if(plci->State==ADVANCED_VOICE_NOSIG)
5760         {
5761           dbug(1,dprintf("***Codec OK"));
5762           if(a->AdvSignalPLCI)
5763           {
5764             tplci = a->AdvSignalPLCI;
5765             if(tplci->spoofed_msg)
5766             {
5767               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5768               tplci->command = 0;
5769               tplci->internal_command = 0;
5770               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5771               switch (tplci->spoofed_msg)
5772               {
5773               case CALL_RES:
5774                 tplci->command = _CONNECT_I|RESPONSE;
5775                 api_load_msg (&tplci->saved_msg, saved_parms);
5776                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5777                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5778                 {
5779                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5780                   add_p(tplci,LLI,"\x01\x01");
5781                 }
5782                 add_s(tplci, CONN_NR, &saved_parms[2]);
5783                 add_s(tplci, LLC, &saved_parms[4]);
5784                 add_ai(tplci, &saved_parms[5]);
5785                 tplci->State = INC_CON_ACCEPT;
5786                 sig_req(tplci, CALL_RES,0);
5787                 send_req(tplci);
5788                 break;
5789 
5790               case AWAITING_SELECT_B:
5791                 dbug(1,dprintf("Select_B continue"));
5792                 start_internal_command (x_Id, tplci, select_b_command);
5793                 break;
5794 
5795               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5796                 if(!tplci->Sig.Id)
5797                 {
5798                   dbug(1,dprintf("No SigID!"));
5799                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5800                   plci_remove(tplci);
5801                   break;
5802                 }
5803                 tplci->command = _MANUFACTURER_R;
5804                 api_load_msg (&tplci->saved_msg, saved_parms);
5805                 dir = saved_parms[2].info[0];
5806                 if(dir==1) {
5807                   sig_req(tplci,CALL_REQ,0);
5808                 }
5809                 else if(!dir){
5810                   sig_req(tplci,LISTEN_REQ,0);
5811                 }
5812                 send_req(tplci);
5813                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5814                 break;
5815 
5816               case (CALL_REQ|AWAITING_MANUF_CON):
5817                 sig_req(tplci,CALL_REQ,0);
5818                 send_req(tplci);
5819                 break;
5820 
5821               case CALL_REQ:
5822                 if(!tplci->Sig.Id)
5823                 {
5824                   dbug(1,dprintf("No SigID!"));
5825                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5826                   plci_remove(tplci);
5827                   break;
5828                 }
5829                 tplci->command = _CONNECT_R;
5830                 api_load_msg (&tplci->saved_msg, saved_parms);
5831                 add_s(tplci,CPN,&saved_parms[1]);
5832                 add_s(tplci,DSA,&saved_parms[3]);
5833                 add_ai(tplci,&saved_parms[9]);
5834                 sig_req(tplci,CALL_REQ,0);
5835                 send_req(tplci);
5836                 break;
5837 
5838               case CALL_RETRIEVE:
5839                 tplci->command = C_RETRIEVE_REQ;
5840                 sig_req(tplci,CALL_RETRIEVE,0);
5841                 send_req(tplci);
5842                 break;
5843               }
5844               tplci->spoofed_msg = 0;
5845               if (tplci->internal_command == 0)
5846                 next_internal_command (x_Id, tplci);
5847             }
5848           }
5849           next_internal_command (Id, plci);
5850           break;
5851         }
5852         dbug(1,dprintf("***Codec Hook Init Req"));
5853         plci->internal_command = PERM_COD_HOOK;
5854         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5855         sig_req(plci,TEL_CTRL,0);
5856         send_req(plci);
5857       }
5858     }
5859     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5860     && plci->State!=INC_ACT_PENDING)
5861     {
5862       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5863       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5864       {
5865         chi[2] = plci->b_channel;
5866         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5867       }
5868       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5869       plci->State = INC_ACT_PENDING;
5870     }
5871     break;
5872 
5873   case TEL_CTRL:
5874     Number = 0;
5875     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5876     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5877       switch (ie[1]&0x91) {
5878         case 0x80:   /* hook off */
5879         case 0x81:
5880           if(plci->internal_command==PERM_COD_HOOK)
5881           {
5882             dbug(1,dprintf("init:hook_off"));
5883             plci->hook_state = ie[1];
5884             next_internal_command (Id, plci);
5885             break;
5886           }
5887           else /* ignore doubled hook indications */
5888           {
5889             if( ((plci->hook_state)&0xf0)==0x80)
5890             {
5891               dbug(1,dprintf("ignore hook"));
5892               break;
5893             }
5894             plci->hook_state = ie[1]&0x91;
5895           }
5896           /* check for incoming call pending */
5897           /* and signal '+'.Appl must decide */
5898           /* with connect_res if call must   */
5899           /* accepted or not                 */
5900           for(i=0, tplci=NULL;i<max_appl;i++){
5901             if(a->codec_listen[i]
5902             && (a->codec_listen[i]->State==INC_CON_PENDING
5903               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5904               tplci = a->codec_listen[i];
5905               tplci->appl = &application[i];
5906             }
5907           }
5908           /* no incoming call, do outgoing call */
5909           /* and signal '+' if outg. setup   */
5910           if(!a->AdvSignalPLCI && !tplci){
5911             if((i=get_plci(a))) {
5912               a->AdvSignalPLCI = &a->plci[i-1];
5913               tplci = a->AdvSignalPLCI;
5914               tplci->tel  = ADV_VOICE;
5915               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5916               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5917                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5918                 add_p(tplci,LLI,"\x01\x01");
5919               }
5920               add_p(tplci, CAI, voice_cai);
5921               add_p(tplci, OAD, a->TelOAD);
5922               add_p(tplci, OSA, a->TelOSA);
5923               add_p(tplci,SHIFT|6,NULL);
5924               add_p(tplci,SIN,"\x02\x01\x00");
5925               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5926               sig_req(tplci,ASSIGN,DSIG_ID);
5927               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5928               a->AdvSignalPLCI->command = 0;
5929               tplci->appl = a->AdvSignalAppl;
5930               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5931               send_req(tplci);
5932             }
5933 
5934           }
5935 
5936           if(!tplci) break;
5937           Id = ((word)tplci->Id<<8)|a->Id;
5938           Id|=EXT_CONTROLLER;
5939           sendf(tplci->appl,
5940                 _FACILITY_I,
5941                 Id,
5942                 0,
5943                 "ws", (word)0, "\x01+");
5944           break;
5945 
5946         case 0x90:   /* hook on  */
5947         case 0x91:
5948           if(plci->internal_command==PERM_COD_HOOK)
5949           {
5950             dbug(1,dprintf("init:hook_on"));
5951             plci->hook_state = ie[1]&0x91;
5952             next_internal_command (Id, plci);
5953             break;
5954           }
5955           else /* ignore doubled hook indications */
5956           {
5957             if( ((plci->hook_state)&0xf0)==0x90) break;
5958             plci->hook_state = ie[1]&0x91;
5959           }
5960           /* hangup the adv. voice call and signal '-' to the appl */
5961           if(a->AdvSignalPLCI) {
5962             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5963             if(plci->tel) Id|=EXT_CONTROLLER;
5964             sendf(a->AdvSignalAppl,
5965                   _FACILITY_I,
5966                   Id,
5967                   0,
5968                   "ws", (word)0, "\x01-");
5969             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5970             a->AdvSignalPLCI->command = 0;
5971             sig_req(a->AdvSignalPLCI,HANGUP,0);
5972             send_req(a->AdvSignalPLCI);
5973           }
5974           break;
5975       }
5976     }
5977     break;
5978 
5979   case RESUME:
5980     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5981     PUT_WORD(&resume_cau[4],GOOD);
5982     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5983     break;
5984 
5985   case SUSPEND:
5986     clear_c_ind_mask (plci);
5987 
5988     if (plci->NL.Id && !plci->nl_remove_id) {
5989       mixer_remove (plci);
5990       nl_req_ncci(plci,REMOVE,0);
5991     }
5992     if (!plci->sig_remove_id) {
5993       plci->internal_command = 0;
5994       sig_req(plci,REMOVE,0);
5995     }
5996     send_req(plci);
5997     if(!plci->channels) {
5998       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5999       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6000     }
6001     break;
6002 
6003   case SUSPEND_REJ:
6004     break;
6005 
6006   case HANGUP:
6007     plci->hangup_flow_ctrl_timer=0;
6008     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6009     cau = parms[7];
6010     if(cau) {
6011       i = _L3_CAUSE | cau[2];
6012       if(cau[2]==0) i = 0;
6013       else if(cau[2]==8) i = _L1_ERROR;
6014       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6015       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6016     }
6017     else {
6018       i = _L3_ERROR;
6019     }
6020 
6021     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6022     {
6023       for(i=0; i<max_appl; i++)
6024       {
6025         if(test_c_ind_mask_bit (plci, i))
6026           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6027       }
6028     }
6029     else
6030     {
6031       clear_c_ind_mask (plci);
6032     }
6033     if(!plci->appl)
6034     {
6035       if (plci->State == LISTENING)
6036       {
6037         plci->notifiedcall=0;
6038         a->listen_active--;
6039       }
6040       plci->State = INC_DIS_PENDING;
6041       if(c_ind_mask_empty (plci))
6042       {
6043         plci->State = IDLE;
6044         if (plci->NL.Id && !plci->nl_remove_id)
6045         {
6046           mixer_remove (plci);
6047           nl_req_ncci(plci,REMOVE,0);
6048         }
6049         if (!plci->sig_remove_