Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[sfrench/cifs-2.6.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3   Copyright (c) Eicon Networks, 2002.
4  *
5   This source file is supplied for the use with
6   Eicon Networks range of DIVA Server Adapters.
7  *
8   Eicon File Revision :    2.1
9  *
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2, or (at your option)
13   any later version.
14  *
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18   See the GNU General Public License for more details.
19  *
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67  */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
75 static void set_group_ind_mask (PLCI   *plci);
76 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
77 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL   *, CAPI_MSG   *);
82 static word api_parse(byte   *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
84 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI   *);
90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
92
93 void   callback(ENTITY   *);
94
95 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI   *, byte);
97 static void data_ack(PLCI   *, byte);
98 static void sig_ind(PLCI   *);
99 static void SendInfo(PLCI   *, dword, byte   * *, byte);
100 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
101 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
102
103 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
104
105 static void nl_ind(PLCI   *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER   *);
133 static void add_p(PLCI   *, byte, byte   *);
134 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
137 static void add_d(PLCI   *, word, byte   *);
138 static void add_ai(PLCI   *, API_PARSE *);
139 static word add_b1(PLCI   *, API_PARSE *, word, word);
140 static word add_b23(PLCI   *, API_PARSE *);
141 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI   *, byte, byte);
143 static void nl_req_ncci(PLCI   *, byte, byte);
144 static void send_req(PLCI   *);
145 static void send_data(PLCI   *);
146 static word plci_remove_check(PLCI   *);
147 static void listen_check(DIVA_CAPI_ADAPTER   *);
148 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI   *, word *, byte   **, byte);
151 static byte ie_compare(byte   *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
153 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
154
155 /*
156   XON protocol helpers
157   */
158 static void channel_flow_control_remove (PLCI   * plci);
159 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI   * plci, byte ch);
161 static void channel_request_xon (PLCI   * plci, byte ch);
162 static void channel_xmit_xon (PLCI   * plci);
163 static int channel_can_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI   * plci);
165
166 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
169 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
170 static void VoiceChannelOff(PLCI   *plci);
171 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
172 static void adv_voice_clear_config (PLCI   *plci);
173
174 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
189 static void init_b1_config (PLCI   *plci);
190 static void clear_b1_config (PLCI   *plci);
191
192 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI   *plci);
195 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
196 static void dtmf_parameter_write (PLCI   *plci);
197
198
199 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
201 static void mixer_clear_config (PLCI   *plci);
202 static void mixer_notify_update (PLCI   *plci, byte others);
203 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_remove (PLCI   *plci);
209
210
211 static void ec_command (dword Id, PLCI   *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
214
215
216 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
218
219
220 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
221 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231
232 void   sendf(APPL   *, word, dword, word, byte *, ...);
233 void   * TransmitBufferSet(APPL   * appl, dword ref);
234 void   * TransmitBufferGet(APPL   * appl, void   * p);
235 void TransmitBufferFree(APPL   * appl, void   * p);
236 void   * ReceiveBufferGet(APPL   * appl, int Num);
237
238 int fax_head_line_time (char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER   * adapter;
247 extern APPL   * application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260   word command;
261   byte * format;
262   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
263 } ftable[] = {
264   {_DATA_B3_R,                          "dwww",         data_b3_req},
265   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
266   {_INFO_R,                             "ss",           info_req},
267   {_INFO_I|RESPONSE,                    "",             info_res},
268   {_CONNECT_R,                          "wsssssssss",   connect_req},
269   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
270   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
271   {_DISCONNECT_R,                       "s",            disconnect_req},
272   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
273   {_LISTEN_R,                           "dddss",        listen_req},
274   {_ALERT_R,                            "s",            alert_req},
275   {_FACILITY_R,                         "ws",           facility_req},
276   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
277   {_CONNECT_B3_R,                       "s",            connect_b3_req},
278   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
279   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
280   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
282   {_RESET_B3_R,                         "s",            reset_b3_req},
283   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
284   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
286   {_SELECT_B_REQ,                       "s",            select_b_req},
287   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
289   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
290 };
291
292 static byte * cip_bc[29][2] = {
293   { "",                     ""                     }, /* 0 */
294   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303   { "",                     ""                     }, /* 10 */
304   { "",                     ""                     }, /* 11 */
305   { "",                     ""                     }, /* 12 */
306   { "",                     ""                     }, /* 13 */
307   { "",                     ""                     }, /* 14 */
308   { "",                     ""                     }, /* 15 */
309
310   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte * cip_hlc[29] = {
326   "",                           /* 0 */
327   "",                           /* 1 */
328   "",                           /* 2 */
329   "",                           /* 3 */
330   "",                           /* 4 */
331   "",                           /* 5 */
332   "",                           /* 6 */
333   "",                           /* 7 */
334   "",                           /* 8 */
335   "",                           /* 9 */
336   "",                           /* 10 */
337   "",                           /* 11 */
338   "",                           /* 12 */
339   "",                           /* 13 */
340   "",                           /* 14 */
341   "",                           /* 15 */
342
343   "\x02\x91\x81",               /* 16 */
344   "\x02\x91\x84",               /* 17 */
345   "\x02\x91\xa1",               /* 18 */
346   "\x02\x91\xa4",               /* 19 */
347   "\x02\x91\xa8",               /* 20 */
348   "\x02\x91\xb1",               /* 21 */
349   "\x02\x91\xb2",               /* 22 */
350   "\x02\x91\xb5",               /* 23 */
351   "\x02\x91\xb8",               /* 24 */
352   "\x02\x91\xc1",               /* 25 */
353   "\x02\x91\x81",               /* 26 */
354   "\x03\x91\xe0\x01",           /* 27 */
355   "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL   * appl, CAPI_MSG   * msg)
387 {
388   word i, j, k, l, n;
389   word ret;
390   byte c;
391   byte controller;
392   DIVA_CAPI_ADAPTER   * a;
393   PLCI   * plci;
394   NCCI   * ncci_ptr;
395   word ncci;
396   CAPI_MSG   *m;
397     API_PARSE msg_parms[MAX_MSG_PARMS+1];
398
399   if (msg->header.length < sizeof (msg->header) ||
400       msg->header.length > MAX_MSG_SIZE) {
401     dbug(1,dprintf("bad len"));
402     return _BAD_MSG;
403   }
404
405   controller = (byte)((msg->header.controller &0x7f)-1);
406
407   /* controller starts with 0 up to (max_adapter - 1) */
408   if ( controller >= max_adapter )
409   {
410     dbug(1,dprintf("invalid ctrl"));
411     return _BAD_MSG;
412   }
413   
414   a = &adapter[controller];
415   plci = NULL;
416   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417   {
418     dbug(1,dprintf("plci=%x",msg->header.plci));
419     plci = &a->plci[msg->header.plci-1];
420     ncci = GET_WORD(&msg->header.ncci);
421     if (plci->Id
422      && (plci->appl
423       || (plci->State == INC_CON_PENDING)
424       || (plci->State == INC_CON_ALERT)
425       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426      && ((ncci == 0)
427       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429     {
430       i = plci->msg_in_read_pos;
431       j = plci->msg_in_write_pos;
432       if (j >= i)
433       {
434         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435           i += MSG_IN_QUEUE_SIZE - j;
436         else
437           j = 0;
438       }
439       else
440       {
441
442         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444         if (i > MSG_IN_QUEUE_SIZE - n)
445           i = MSG_IN_QUEUE_SIZE - n + 1;
446         i -= j;
447       }
448
449       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451       {
452         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453           msg->header.length, plci->msg_in_write_pos,
454           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456         return _QUEUE_FULL;
457       }
458       c = false;
459       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
460        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461       {
462         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463           c = true;
464       }
465       if (msg->header.command == _DATA_B3_R)
466       {
467         if (msg->header.length < 20)
468         {
469           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470           return _BAD_MSG;
471         }
472         ncci_ptr = &(a->ncci[ncci]);
473         n = ncci_ptr->data_pending;
474         l = ncci_ptr->data_ack_pending;
475         k = plci->msg_in_read_pos;
476         while (k != plci->msg_in_write_pos)
477         {
478           if (k == plci->msg_in_wrap_pos)
479             k = 0;
480           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482           {
483             n++;
484             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485               l++;
486           }
487
488           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
489             MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491         }
492         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493         {
494           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497           return _QUEUE_FULL;
498         }
499         if (plci->req_in || plci->internal_command)
500         {
501           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
502            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503           {
504             dbug(0,dprintf("Q-FULL3(requeue)"));
505
506             return _QUEUE_FULL;
507           }
508           c = true;
509         }
510       }
511       else
512       {
513         if (plci->req_in || plci->internal_command)
514           c = true;
515         else
516         {
517           plci->command = msg->header.command;
518           plci->number = msg->header.number;
519         }
520       }
521       if (c)
522       {
523         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524           msg->header.command, plci->req_in, plci->internal_command,
525           msg->header.length, plci->msg_in_write_pos,
526           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527         if (j == 0)
528           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
530         for (i = 0; i < msg->header.length; i++)
531           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
532         if (m->header.command == _DATA_B3_R)
533         {
534
535           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
536
537         }
538
539         j = (j + 3) & 0xfffc;
540
541         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
542         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543         return 0;
544       }
545     }
546     else
547     {
548       plci = NULL;
549     }
550   }
551   dbug(1,dprintf("com=%x",msg->header.command));
552
553   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554   for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
555
556     if(ftable[i].command==msg->header.command) {
557       /* break loop if the message is correct, otherwise continue scan  */
558       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
559       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
560         ret = 0;
561         break;
562       }
563       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
564     }
565   }
566   if(ret) {
567     dbug(1,dprintf("BAD_MSG"));
568     if(plci) plci->command = 0;
569     return ret;
570   }
571
572
573   c = ftable[i].function(GET_DWORD(&msg->header.controller),
574                          msg->header.number,
575                          a,
576                          plci,
577                          appl,
578                          msg_parms);
579
580   channel_xmit_extended_xon (plci);
581
582   if(c==1) send_req(plci);
583   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584   if(plci && !plci->req_in) plci->command = 0;
585   return 0;
586 }
587
588
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages             */
591 /*------------------------------------------------------------------*/
592
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
594 {
595   word i;
596   word p;
597
598   for(i=0,p=0; format[i]; i++) {
599     if(parms)
600     {
601       parms[i].info = &msg[p];
602     }
603     switch(format[i]) {
604     case 'b':
605       p +=1;
606       break;
607     case 'w':
608       p +=2;
609       break;
610     case 'd':
611       p +=4;
612       break;
613     case 's':
614       if(msg[p]==0xff) {
615         parms[i].info +=2;
616         parms[i].length = msg[p+1] + (msg[p+2]<<8);
617         p +=(parms[i].length +3);
618       }
619       else {
620         parms[i].length = msg[p];
621         p +=(parms[i].length +1);
622       }
623       break;
624     }
625
626     if(p>length) return true;
627   }
628   if(parms) parms[i].info = NULL;
629   return false;
630 }
631
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
633 {
634   word i, j, n = 0;
635   byte   *p;
636
637   p = out->info;
638   for (i = 0; format[i] != '\0'; i++)
639   {
640     out->parms[i].info = p;
641     out->parms[i].length = in[i].length;
642     switch (format[i])
643     {
644     case 'b':
645       n = 1;
646       break;
647     case 'w':
648       n = 2;
649       break;
650     case 'd':
651       n = 4;
652       break;
653     case 's':
654       n = in[i].length + 1;
655       break;
656     }
657     for (j = 0; j < n; j++)
658       *(p++) = in[i].info[j];
659   }
660   out->parms[i].info = NULL;
661   out->parms[i].length = 0;
662 }
663
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
665 {
666   word i;
667
668   i = 0;
669   do
670   {
671     out[i].info = in->parms[i].info;
672     out[i].length = in->parms[i].length;
673   } while (in->parms[i++].info);
674 }
675
676
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function                                             */
679 /*------------------------------------------------------------------*/
680
681 word api_remove_start(void)
682 {
683   word i;
684   word j;
685
686   if(!remove_started) {
687     remove_started = true;
688     for(i=0;i<max_adapter;i++) {
689       if(adapter[i].request) {
690         for(j=0;j<adapter[i].max_plci;j++) {
691           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692         }
693       }
694     }
695     return 1;
696   }
697   else {
698     for(i=0;i<max_adapter;i++) {
699       if(adapter[i].request) {
700         for(j=0;j<adapter[i].max_plci;j++) {
701           if(adapter[i].plci[j].Sig.Id) return 1;
702         }
703       }
704     }
705   }
706   api_remove_complete();
707   return 0;
708 }
709
710
711 /*------------------------------------------------------------------*/
712 /* internal command queue                                           */
713 /*------------------------------------------------------------------*/
714
715 static void init_internal_command_queue (PLCI   *plci)
716 {
717   word i;
718
719   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
720     (char   *)(FILE_), __LINE__));
721
722   plci->internal_command = 0;
723   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724     plci->internal_command_queue[i] = NULL;
725 }
726
727
728 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
729 {
730   word i;
731
732   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
733     UnMapId (Id), (char   *)(FILE_), __LINE__));
734
735   if (plci->internal_command == 0)
736   {
737     plci->internal_command_queue[0] = command_function;
738     (* command_function)(Id, plci, OK);
739   }
740   else
741   {
742     i = 1;
743     while (plci->internal_command_queue[i] != NULL)
744       i++;
745     plci->internal_command_queue[i] = command_function;
746   }
747 }
748
749
750 static void next_internal_command (dword Id, PLCI   *plci)
751 {
752   word i;
753
754   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
755     UnMapId (Id), (char   *)(FILE_), __LINE__));
756
757   plci->internal_command = 0;
758   plci->internal_command_queue[0] = NULL;
759   while (plci->internal_command_queue[1] != NULL)
760   {
761     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
763     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764     (*(plci->internal_command_queue[0]))(Id, plci, OK);
765     if (plci->internal_command != 0)
766       return;
767     plci->internal_command_queue[0] = NULL;
768   }
769 }
770
771
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function                                    */
774 /*------------------------------------------------------------------*/
775
776 static dword ncci_mapping_bug = 0;
777
778 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
779 {
780   DIVA_CAPI_ADAPTER   *a;
781   word ncci, i, j, k;
782
783   a = plci->adapter;
784   if (!ch || a->ch_ncci[ch])
785   {
786     ncci_mapping_bug++;
787     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789     ncci = ch;
790   }
791   else
792   {
793     if (force_ncci)
794       ncci = force_ncci;
795     else
796     {
797       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
798         ncci = ch;
799       else
800       {
801         ncci = 1;
802         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
803           ncci++;
804         if (ncci == MAX_NCCI+1)
805         {
806           ncci_mapping_bug++;
807           i = 1;
808           do
809           {
810             j = 1;
811             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
812               j++;
813             k = j;
814             if (j < MAX_NCCI+1)
815             {
816               do
817               {
818                 j++;
819               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
820             }
821           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
822           if (i < MAX_NL_CHANNEL+1)
823           {
824             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825               ncci_mapping_bug, ch, force_ncci, i, k, j));
826           }
827           else
828           {
829             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
830               ncci_mapping_bug, ch, force_ncci));
831           }
832           ncci = ch;
833         }
834       }
835       a->ncci_plci[ncci] = plci->Id;
836       a->ncci_state[ncci] = IDLE;
837       if (!plci->ncci_ring_list)
838         plci->ncci_ring_list = ncci;
839       else
840         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842     }
843     a->ncci_ch[ncci] = ch;
844     a->ch_ncci[ch] = (byte) ncci;
845     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846       ncci_mapping_bug, ch, force_ncci, ch, ncci));
847   }
848   return (ncci);
849 }
850
851
852 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
853 {
854   DIVA_CAPI_ADAPTER   *a;
855   APPL   *appl;
856   word i, ncci_code;
857   dword Id;
858
859   a = plci->adapter;
860   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861   if (ncci)
862   {
863     if (a->ncci_plci[ncci] == plci->Id)
864     {
865       if (!plci->appl)
866       {
867         ncci_mapping_bug++;
868         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
869           ncci_mapping_bug, Id));
870       }
871       else
872       {
873         appl = plci->appl;
874         ncci_code = ncci | (((word) a->Id) << 8);
875         for (i = 0; i < appl->MaxBuffer; i++)
876         {
877           if ((appl->DataNCCI[i] == ncci_code)
878            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879           {
880             appl->DataNCCI[i] = 0;
881           }
882         }
883       }
884     }
885   }
886   else
887   {
888     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
889     {
890       if (a->ncci_plci[ncci] == plci->Id)
891       {
892         if (!plci->appl)
893         {
894           ncci_mapping_bug++;
895           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
896             ncci_mapping_bug, Id));
897         }
898         else
899         {
900           appl = plci->appl;
901           ncci_code = ncci | (((word) a->Id) << 8);
902           for (i = 0; i < appl->MaxBuffer; i++)
903           {
904             if ((appl->DataNCCI[i] == ncci_code)
905              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906             {
907               appl->DataNCCI[i] = 0;
908             }
909           }
910         }
911       }
912     }
913   }
914 }
915
916
917 static void cleanup_ncci_data (PLCI   *plci, word ncci)
918 {
919   NCCI   *ncci_ptr;
920
921   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922   {
923     ncci_ptr = &(plci->adapter->ncci[ncci]);
924     if (plci->appl)
925     {
926       while (ncci_ptr->data_pending != 0)
927       {
928         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930         (ncci_ptr->data_out)++;
931         if (ncci_ptr->data_out == MAX_DATA_B3)
932           ncci_ptr->data_out = 0;
933         (ncci_ptr->data_pending)--;
934       }
935     }
936     ncci_ptr->data_out = 0;
937     ncci_ptr->data_pending = 0;
938     ncci_ptr->data_ack_out = 0;
939     ncci_ptr->data_ack_pending = 0;
940   }
941 }
942
943
944 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
945 {
946   DIVA_CAPI_ADAPTER   *a;
947   dword Id;
948   word i;
949
950   a = plci->adapter;
951   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952   if (!preserve_ncci)
953     ncci_free_receive_buffers (plci, ncci);
954   if (ncci)
955   {
956     if (a->ncci_plci[ncci] != plci->Id)
957     {
958       ncci_mapping_bug++;
959       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960         ncci_mapping_bug, Id, preserve_ncci));
961     }
962     else
963     {
964       cleanup_ncci_data (plci, ncci);
965       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967       a->ch_ncci[a->ncci_ch[ncci]] = 0;
968       if (!preserve_ncci)
969       {
970         a->ncci_ch[ncci] = 0;
971         a->ncci_plci[ncci] = 0;
972         a->ncci_state[ncci] = IDLE;
973         i = plci->ncci_ring_list;
974         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975           i = a->ncci_next[i];
976         if ((i != 0) && (a->ncci_next[i] == ncci))
977         {
978           if (i == ncci)
979             plci->ncci_ring_list = 0;
980           else if (plci->ncci_ring_list == ncci)
981             plci->ncci_ring_list = i;
982           a->ncci_next[i] = a->ncci_next[ncci];
983         }
984         a->ncci_next[ncci] = 0;
985       }
986     }
987   }
988   else
989   {
990     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
991     {
992       if (a->ncci_plci[ncci] == plci->Id)
993       {
994         cleanup_ncci_data (plci, ncci);
995         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997         a->ch_ncci[a->ncci_ch[ncci]] = 0;
998         if (!preserve_ncci)
999         {
1000           a->ncci_ch[ncci] = 0;
1001           a->ncci_plci[ncci] = 0;
1002           a->ncci_state[ncci] = IDLE;
1003           a->ncci_next[ncci] = 0;
1004         }
1005       }
1006     }
1007     if (!preserve_ncci)
1008       plci->ncci_ring_list = 0;
1009   }
1010 }
1011
1012
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function                                             */
1015 /*------------------------------------------------------------------*/
1016
1017 static void plci_free_msg_in_queue (PLCI   *plci)
1018 {
1019   word i;
1020
1021   if (plci->appl)
1022   {
1023     i = plci->msg_in_read_pos;
1024     while (i != plci->msg_in_write_pos)
1025     {
1026       if (i == plci->msg_in_wrap_pos)
1027         i = 0;
1028       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029       {
1030
1031         TransmitBufferFree (plci->appl,
1032           (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033
1034       }
1035
1036       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1037         MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039     }
1040   }
1041   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044 }
1045
1046
1047 static void plci_remove(PLCI   * plci)
1048 {
1049
1050   if(!plci) {
1051     dbug(1,dprintf("plci_remove(no plci)"));
1052     return;
1053   }
1054   init_internal_command_queue (plci);
1055   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1056   if(plci_remove_check(plci))
1057   {
1058     return;
1059   }
1060   if (plci->Sig.Id == 0xff)
1061   {
1062     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063     if (plci->NL.Id && !plci->nl_remove_id)
1064     {
1065       nl_req_ncci(plci,REMOVE,0);
1066       send_req(plci);
1067     }
1068   }
1069   else
1070   {
1071     if (!plci->sig_remove_id
1072      && (plci->Sig.Id
1073       || (plci->req_in!=plci->req_out)
1074       || (plci->nl_req || plci->sig_req)))
1075     {
1076       sig_req(plci,HANGUP,0);
1077       send_req(plci);
1078     }
1079   }
1080   ncci_remove (plci, 0, false);
1081   plci_free_msg_in_queue (plci);
1082
1083   plci->channels = 0;
1084   plci->appl = NULL;
1085   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086     plci->State = OUTG_DIS_PENDING;
1087 }
1088
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers                               */
1091 /*------------------------------------------------------------------*/
1092
1093 static void set_group_ind_mask (PLCI   *plci)
1094 {
1095   word i;
1096
1097   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098     plci->group_optimization_mask_table[i] = 0xffffffffL;
1099 }
1100
1101 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1102 {
1103   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104 }
1105
1106 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1107 {
1108   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109 }
1110
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1113 /*------------------------------------------------------------------*/
1114
1115 static void clear_c_ind_mask (PLCI   *plci)
1116 {
1117   word i;
1118
1119   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120     plci->c_ind_mask_table[i] = 0;
1121 }
1122
1123 static byte c_ind_mask_empty (PLCI   *plci)
1124 {
1125   word i;
1126
1127   i = 0;
1128   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129     i++;
1130   return (i == C_IND_MASK_DWORDS);
1131 }
1132
1133 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1134 {
1135   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136 }
1137
1138 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1139 {
1140   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141 }
1142
1143 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1144 {
1145   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146 }
1147
1148 static void dump_c_ind_mask (PLCI   *plci)
1149 {
1150 static char hex_digit_table[0x10] =
1151   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1152   word i, j, k;
1153   dword d;
1154     char *p;
1155     char buf[40];
1156
1157   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158   {
1159     p = buf + 36;
1160     *p = '\0';
1161     for (j = 0; j < 4; j++)
1162     {
1163       if (i+j < C_IND_MASK_DWORDS)
1164       {
1165         d = plci->c_ind_mask_table[i+j];
1166         for (k = 0; k < 8; k++)
1167         {
1168           *(--p) = hex_digit_table[d & 0xf];
1169           d >>= 4;
1170         }
1171       }
1172       else if (i != 0)
1173       {
1174         for (k = 0; k < 8; k++)
1175           *(--p) = ' ';
1176       }
1177       *(--p) = ' ';
1178     }
1179     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1180   }
1181 }
1182
1183
1184
1185
1186
1187 #define dump_plcis(a)
1188
1189
1190
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message                            */
1193 /*------------------------------------------------------------------*/
1194
1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196                         PLCI *plci, APPL *appl, API_PARSE *parms)
1197 {
1198   word ch;
1199   word i;
1200   word Info;
1201   word CIP;
1202   byte LinkLayer;
1203   API_PARSE * ai;
1204   API_PARSE * bp;
1205     API_PARSE ai_parms[5];
1206   word channel = 0;
1207   dword ch_mask;
1208   byte m;
1209   static byte esc_chi[35] = {0x02,0x18,0x01};
1210   static byte lli[2] = {0x01,0x00};
1211   byte noCh = 0;
1212   word dir = 0;
1213   byte   *p_chi = "";
1214
1215   for(i=0;i<5;i++) ai_parms[i].length = 0;
1216
1217   dbug(1,dprintf("connect_req(%d)",parms->length));
1218   Info = _WRONG_IDENTIFIER;
1219   if(a)
1220   {
1221     if(a->adapter_disabled)
1222     {
1223       dbug(1,dprintf("adapter disabled"));
1224       Id = ((word)1<<8)|a->Id;
1225       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1226       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1227       return false;
1228     }
1229     Info = _OUT_OF_PLCI;
1230     if((i=get_plci(a)))
1231     {
1232       Info = 0;
1233       plci = &a->plci[i-1];
1234       plci->appl = appl;
1235       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1236       /* check 'external controller' bit for codec support */
1237       if(Id & EXT_CONTROLLER)
1238       {
1239         if(AdvCodecSupport(a, plci, appl, 0) )
1240         {
1241           plci->Id = 0;
1242           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1243           return 2;
1244         }
1245       }
1246       ai = &parms[9];
1247       bp = &parms[5];
1248       ch = 0;
1249       if(bp->length)LinkLayer = bp->info[3];
1250       else LinkLayer = 0;
1251       if(ai->length)
1252       {
1253         ch=0xffff;
1254         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1255         {
1256           ch = 0;
1257           if(ai_parms[0].length)
1258           {
1259             ch = GET_WORD(ai_parms[0].info+1);
1260             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1261             if(ch==4) /* explizit CHI in message */
1262             {
1263               /* check length of B-CH struct */
1264               if((ai_parms[0].info)[3]>=1)
1265               {
1266                 if((ai_parms[0].info)[4]==CHI)
1267                 {
1268                   p_chi = &((ai_parms[0].info)[5]);
1269                 }
1270                 else
1271                 {
1272                   p_chi = &((ai_parms[0].info)[3]);
1273                 }
1274                 if(p_chi[0]>35) /* check length of channel ID */
1275                 {
1276                   Info = _WRONG_MESSAGE_FORMAT;    
1277                 }
1278               }
1279               else Info = _WRONG_MESSAGE_FORMAT;    
1280             }
1281
1282             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1283             {
1284               dir = GET_WORD(ai_parms[0].info+3);
1285               ch_mask = 0;
1286               m = 0x3f;
1287               for(i=0; i+5<=ai_parms[0].length; i++)
1288               {
1289                 if(ai_parms[0].info[i+5]!=0)
1290                 {
1291                   if((ai_parms[0].info[i+5] | m) != 0xff)
1292                     Info = _WRONG_MESSAGE_FORMAT;
1293                   else
1294                   {
1295                     if (ch_mask == 0)
1296                       channel = i;
1297                     ch_mask |= 1L << i;
1298                   }
1299                 }
1300                 m = 0;
1301               }
1302               if (ch_mask == 0)
1303                 Info = _WRONG_MESSAGE_FORMAT;
1304               if (!Info)
1305               {
1306                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1307                 {
1308                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1309                   for(i=0; i+5<=ai_parms[0].length; i++)
1310                     esc_chi[i+3] = ai_parms[0].info[i+5];
1311                 }
1312                 else
1313                   esc_chi[0] = 2;
1314                 esc_chi[2] = (byte)channel;
1315                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1316                 add_p(plci,LLI,lli);
1317                 add_p(plci,ESC,esc_chi);
1318                 plci->State = LOCAL_CONNECT;
1319                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1320               }
1321             }
1322           }
1323         }
1324         else  Info = _WRONG_MESSAGE_FORMAT;
1325       }
1326
1327       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1328       plci->command = _CONNECT_R;
1329       plci->number = Number;
1330       /* x.31 or D-ch free SAPI in LinkLayer? */
1331       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1332       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1333       {
1334         /* B-channel used for B3 connections (ch==0), or no B channel    */
1335         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1336         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1337         else     Info = add_b1(plci,&parms[5],ch,0); 
1338         add_s(plci,OAD,&parms[2]);
1339         add_s(plci,OSA,&parms[4]);
1340         add_s(plci,BC,&parms[6]);
1341         add_s(plci,LLC,&parms[7]);
1342         add_s(plci,HLC,&parms[8]);
1343         CIP = GET_WORD(parms[0].info);
1344         if (a->Info_Mask[appl->Id-1] & 0x200)
1345         {
1346           /* early B3 connect (CIP mask bit 9) no release after a disc */
1347           add_p(plci,LLI,"\x01\x01");
1348         }
1349         if(GET_WORD(parms[0].info)<29) {
1350           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1351           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1352         }
1353         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1354         sig_req(plci,ASSIGN,DSIG_ID);
1355       }
1356       else if(ch==1) {
1357
1358         /* D-Channel used for B3 connections */
1359         plci->Sig.Id = 0xff;
1360         Info = 0;
1361       }
1362
1363       if(!Info && ch!=2 && !noCh ) {
1364         Info = add_b23(plci,&parms[5]);
1365         if(!Info) {
1366           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1367         }
1368       }
1369
1370       if(!Info)
1371       {
1372         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1373         {
1374           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1375           {
1376             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1377             plci->spoofed_msg = CALL_REQ;
1378             plci->internal_command = BLOCK_PLCI;
1379             plci->command = 0;
1380             dbug(1,dprintf("Spoof"));
1381             send_req(plci);
1382             return false;
1383           }
1384           if(ch==4)add_p(plci,CHI,p_chi);
1385           add_s(plci,CPN,&parms[1]);
1386           add_s(plci,DSA,&parms[3]);
1387           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1388           add_ai(plci,&parms[9]);
1389           if(!dir)sig_req(plci,CALL_REQ,0);
1390           else
1391           {
1392             plci->command = PERM_LIST_REQ;
1393             plci->appl = appl;
1394             sig_req(plci,LISTEN_REQ,0);
1395             send_req(plci);
1396             return false;
1397           }
1398         }
1399         send_req(plci);
1400         return false;
1401       }
1402       plci->Id = 0;
1403     }
1404   }
1405   sendf(appl,
1406         _CONNECT_R|CONFIRM,
1407         Id,
1408         Number,
1409         "w",Info);
1410   return 2;
1411 }
1412
1413 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1414                         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 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1571                           PLCI *plci, APPL *appl, API_PARSE *msg)
1572 {
1573   dbug(1,dprintf("connect_a_res"));
1574   return false;
1575 }
1576
1577 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1578                            PLCI *plci, APPL *appl, API_PARSE *msg)
1579 {
1580   word Info;
1581   word i;
1582
1583   dbug(1,dprintf("disconnect_req"));
1584
1585   Info = _WRONG_IDENTIFIER;
1586
1587   if(plci)
1588   {
1589     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1590     {
1591       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1592       plci->appl = appl;
1593       for(i=0; i<max_appl; i++)
1594       {
1595         if(test_c_ind_mask_bit (plci, i))
1596           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1597       }
1598       plci->State = OUTG_DIS_PENDING;
1599     }
1600     if(plci->Sig.Id && plci->appl)
1601     {
1602       Info = 0;
1603         if(plci->Sig.Id!=0xff)
1604         {
1605           if(plci->State!=INC_DIS_PENDING)
1606           {
1607             add_ai(plci, &msg[0]);
1608             sig_req(plci,HANGUP,0);
1609             plci->State = OUTG_DIS_PENDING;
1610             return 1;
1611           }
1612         }
1613         else
1614         {
1615           if (plci->NL.Id && !plci->nl_remove_id)
1616           {
1617             mixer_remove (plci);
1618             nl_req_ncci(plci,REMOVE,0);
1619           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1620           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1621           plci->State = INC_DIS_PENDING;
1622           }
1623           return 1;
1624         }
1625       }
1626     }
1627
1628   if(!appl)  return false;
1629   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1630   return false;
1631 }
1632
1633 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1634                            PLCI *plci, APPL *appl, API_PARSE *msg)
1635 {
1636   dbug(1,dprintf("disconnect_res"));
1637   if(plci)
1638   {
1639         /* clear ind mask bit, just in case of collsion of          */
1640         /* DISCONNECT_IND and CONNECT_RES                           */
1641     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1642     ncci_free_receive_buffers (plci, 0);
1643     if(plci_remove_check(plci))
1644     {
1645       return 0;
1646     }
1647     if(plci->State==INC_DIS_PENDING
1648     || plci->State==SUSPENDING) {
1649       if(c_ind_mask_empty (plci)) {
1650         if(plci->State!=SUSPENDING)plci->State = IDLE;
1651         dbug(1,dprintf("chs=%d",plci->channels));
1652         if(!plci->channels) {
1653           plci_remove(plci);
1654         }
1655       }
1656     }
1657   }
1658   return 0;
1659 }
1660
1661 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1662                        PLCI *plci, APPL *appl, API_PARSE *parms)
1663 {
1664   word Info;
1665   byte i;
1666
1667   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1668
1669   Info = _WRONG_IDENTIFIER;
1670   if(a) {
1671     Info = 0;
1672     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1673     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1674     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1675     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1676       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1677     }
1678
1679     /* check if external controller listen and switch listen on or off*/
1680     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1681       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1682         dummy_plci.State = IDLE;
1683         a->codec_listen[appl->Id-1] = &dummy_plci;
1684         a->TelOAD[0] = (byte)(parms[3].length);
1685         for(i=1;parms[3].length>=i && i<22;i++) {
1686           a->TelOAD[i] = parms[3].info[i];
1687         }
1688         a->TelOAD[i] = 0;
1689         a->TelOSA[0] = (byte)(parms[4].length);
1690         for(i=1;parms[4].length>=i && i<22;i++) {
1691           a->TelOSA[i] = parms[4].info[i];
1692         }
1693         a->TelOSA[i] = 0;
1694       }
1695       else Info = 0x2002; /* wrong controller, codec not supported */
1696     }
1697     else{               /* clear listen */
1698       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1699     }
1700   }
1701   sendf(appl,
1702         _LISTEN_R|CONFIRM,
1703         Id,
1704         Number,
1705         "w",Info);
1706
1707   if (a) listen_check(a);
1708   return false;
1709 }
1710
1711 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1712                      PLCI *plci, APPL *appl, API_PARSE *msg)
1713 {
1714   word i;
1715   API_PARSE * ai;
1716   PLCI   * rc_plci = NULL;
1717     API_PARSE ai_parms[5];
1718   word Info = 0;
1719
1720   dbug(1,dprintf("info_req"));
1721   for(i=0;i<5;i++) ai_parms[i].length = 0;
1722
1723   ai = &msg[1];
1724
1725   if(ai->length)
1726   {
1727     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1728     {
1729       dbug(1,dprintf("AddInfo wrong"));
1730       Info = _WRONG_MESSAGE_FORMAT;
1731     }
1732   }
1733   if(!a) Info = _WRONG_STATE;
1734
1735   if(!Info && plci)
1736   {                /* no fac, with CPN, or KEY */
1737     rc_plci = plci;
1738     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1739     {
1740       /* overlap sending option */
1741       dbug(1,dprintf("OvlSnd"));
1742       add_s(plci,CPN,&msg[0]);
1743       add_s(plci,KEY,&ai_parms[1]);
1744       sig_req(plci,INFO_REQ,0);
1745       send_req(plci);
1746       return false;
1747     }
1748
1749     if(plci->State && ai_parms[2].length)
1750     {
1751       /* User_Info option */
1752       dbug(1,dprintf("UUI"));
1753       add_s(plci,UUI,&ai_parms[2]);
1754       sig_req(plci,USER_DATA,0);
1755     }
1756     else if(plci->State && ai_parms[3].length)
1757     {
1758       /* Facility option */
1759       dbug(1,dprintf("FAC"));
1760       add_s(plci,CPN,&msg[0]);
1761       add_ai(plci, &msg[1]);
1762       sig_req(plci,FACILITY_REQ,0);
1763     }
1764     else
1765     {
1766       Info = _WRONG_STATE;
1767     }
1768   }
1769   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1770   {
1771     /* NCR_Facility option -> send UUI and Keypad too */
1772     dbug(1,dprintf("NCR_FAC"));
1773     if((i=get_plci(a)))
1774     {
1775       rc_plci = &a->plci[i-1];
1776       appl->NullCREnable  = true;
1777       rc_plci->internal_command = C_NCR_FAC_REQ;
1778       rc_plci->appl = appl;
1779       add_p(rc_plci,CAI,"\x01\x80");
1780       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1781       sig_req(rc_plci,ASSIGN,DSIG_ID);
1782       send_req(rc_plci);
1783     }
1784     else
1785     {
1786       Info = _OUT_OF_PLCI;
1787     }
1788
1789     if(!Info)
1790     {
1791       add_s(rc_plci,CPN,&msg[0]);
1792       add_ai(rc_plci, &msg[1]);
1793       sig_req(rc_plci,NCR_FACILITY,0);
1794       send_req(rc_plci);
1795       return false;
1796      /* for application controlled supplementary services    */
1797     }
1798   }
1799
1800   if (!rc_plci)
1801   {
1802     Info = _WRONG_MESSAGE_FORMAT;
1803   }
1804
1805   if(!Info)
1806   {
1807     send_req(rc_plci);
1808   }
1809   else
1810   {  /* appl is not assigned to a PLCI or error condition */
1811     dbug(1,dprintf("localInfoCon"));
1812     sendf(appl,
1813           _INFO_R|CONFIRM,
1814           Id,
1815           Number,
1816           "w",Info);
1817   }
1818   return false;
1819 }
1820
1821 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1822                      PLCI *plci, APPL *appl, API_PARSE *msg)
1823 {
1824   dbug(1,dprintf("info_res"));
1825   return false;
1826 }
1827
1828 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1829                       PLCI *plci, APPL *appl, API_PARSE *msg)
1830 {
1831   word Info;
1832   byte ret;
1833
1834   dbug(1,dprintf("alert_req"));
1835
1836   Info = _WRONG_IDENTIFIER;
1837   ret = false;
1838   if(plci) {
1839     Info = _ALERT_IGNORED;
1840     if(plci->State!=INC_CON_ALERT) {
1841       Info = _WRONG_STATE;
1842       if(plci->State==INC_CON_PENDING) {
1843         Info = 0;
1844         plci->State=INC_CON_ALERT;
1845         add_ai(plci, &msg[0]);
1846         sig_req(plci,CALL_ALERT,0);
1847         ret = 1;
1848       }
1849     }
1850   }
1851   sendf(appl,
1852         _ALERT_R|CONFIRM,
1853         Id,
1854         Number,
1855         "w",Info);
1856   return ret;
1857 }
1858
1859 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1860                          PLCI *plci, APPL *appl, API_PARSE *msg)
1861 {
1862   word Info = 0;
1863   word i    = 0;
1864
1865   word selector;
1866   word SSreq;
1867   long relatedPLCIvalue;
1868   DIVA_CAPI_ADAPTER   * relatedadapter;
1869   byte * SSparms  = "";
1870     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1871     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1872   API_PARSE * parms;
1873     API_PARSE ss_parms[11];
1874   PLCI   *rplci;
1875     byte cai[15];
1876   dword d;
1877     API_PARSE dummy;
1878
1879   dbug(1,dprintf("facility_req"));
1880   for(i=0;i<9;i++) ss_parms[i].length = 0;
1881
1882   parms = &msg[1];
1883
1884   if(!a)
1885   {
1886     dbug(1,dprintf("wrong Ctrl"));
1887     Info = _WRONG_IDENTIFIER;
1888   }
1889
1890   selector = GET_WORD(msg[0].info);
1891
1892   if(!Info)
1893   {
1894     switch(selector)
1895     {
1896       case SELECTOR_HANDSET:
1897         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1898         break;
1899
1900       case SELECTOR_SU_SERV:
1901         if(!msg[1].length)
1902         {
1903           Info = _WRONG_MESSAGE_FORMAT;
1904           break;
1905         }
1906         SSreq = GET_WORD(&(msg[1].info[1]));
1907         PUT_WORD(&RCparms[1],SSreq);
1908         SSparms = RCparms;
1909         switch(SSreq)
1910         {
1911           case S_GET_SUPPORTED_SERVICES:
1912             if((i=get_plci(a)))
1913             {
1914               rplci = &a->plci[i-1];
1915               rplci->appl = appl;
1916               add_p(rplci,CAI,"\x01\x80");
1917               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1918               sig_req(rplci,ASSIGN,DSIG_ID);
1919               send_req(rplci);
1920             }
1921             else
1922             {
1923               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1924               SSparms = (byte *)SSstruct;
1925               break;
1926             }
1927             rplci->internal_command = GETSERV_REQ_PEND;
1928             rplci->number = Number;
1929             rplci->appl = appl;
1930             sig_req(rplci,S_SUPPORTED,0);
1931             send_req(rplci);
1932             return false;
1933             break;
1934
1935           case S_LISTEN:
1936             if(parms->length==7)
1937             {
1938               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1939               {
1940                 dbug(1,dprintf("format wrong"));
1941                 Info = _WRONG_MESSAGE_FORMAT;
1942                 break;
1943               }
1944             }
1945             else
1946             {
1947               Info = _WRONG_MESSAGE_FORMAT;
1948               break;
1949             }
1950             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1951             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1952             {
1953               if((i=get_plci(a)))
1954               {
1955                 rplci = &a->plci[i-1];
1956                 rplci->appl = appl;
1957                 add_p(rplci,CAI,"\x01\x80");
1958                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1959                 sig_req(rplci,ASSIGN,DSIG_ID);
1960                 send_req(rplci);
1961               }
1962               else
1963               {
1964                 break;
1965               }
1966               rplci->internal_command = GET_MWI_STATE;
1967               rplci->number = Number;
1968               sig_req(rplci,MWI_POLL,0);
1969               send_req(rplci);
1970             }
1971             break;
1972
1973           case S_HOLD:
1974             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1975             if(plci && plci->State && plci->SuppState==IDLE)
1976             {
1977               plci->SuppState = HOLD_REQUEST;
1978               plci->command = C_HOLD_REQ;
1979               add_s(plci,CAI,&ss_parms[1]);
1980               sig_req(plci,CALL_HOLD,0);
1981               send_req(plci);
1982               return false;
1983             }
1984             else Info = 0x3010;                    /* wrong state           */
1985             break;
1986           case S_RETRIEVE:
1987             if(plci && plci->State && plci->SuppState==CALL_HELD)
1988             {
1989               if(Id & EXT_CONTROLLER)
1990               {
1991                 if(AdvCodecSupport(a, plci, appl, 0))
1992                 {
1993                   Info = 0x3010;                    /* wrong state           */
1994                   break;
1995                 }
1996               }
1997               else plci->tel = 0;
1998
1999               plci->SuppState = RETRIEVE_REQUEST;
2000               plci->command = C_RETRIEVE_REQ;
2001               if(plci->spoofed_msg==SPOOFING_REQUIRED)
2002               {
2003                 plci->spoofed_msg = CALL_RETRIEVE;
2004                 plci->internal_command = BLOCK_PLCI;
2005                 plci->command = 0;
2006                 dbug(1,dprintf("Spoof"));
2007                 return false;
2008               }
2009               else
2010               {
2011                 sig_req(plci,CALL_RETRIEVE,0);
2012                 send_req(plci);
2013                 return false;
2014               }
2015             }
2016             else Info = 0x3010;                    /* wrong state           */
2017             break;
2018           case S_SUSPEND:
2019             if(parms->length)
2020             {
2021               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2022               {
2023                 dbug(1,dprintf("format wrong"));
2024                 Info = _WRONG_MESSAGE_FORMAT;
2025                 break;
2026               }
2027             }
2028             if(plci && plci->State)
2029             {
2030               add_s(plci,CAI,&ss_parms[2]);
2031               plci->command = SUSPEND_REQ;
2032               sig_req(plci,SUSPEND,0);
2033               plci->State = SUSPENDING;
2034               send_req(plci);
2035             }
2036             else Info = 0x3010;                    /* wrong state           */
2037             break;
2038
2039           case S_RESUME:
2040             if(!(i=get_plci(a)) )
2041             {
2042               Info = _OUT_OF_PLCI;
2043               break;
2044             }
2045             rplci = &a->plci[i-1];
2046             rplci->appl = appl;
2047             rplci->number = Number;
2048             rplci->tel = 0;
2049             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2050             /* check 'external controller' bit for codec support */
2051             if(Id & EXT_CONTROLLER)
2052             {
2053               if(AdvCodecSupport(a, rplci, appl, 0) )
2054               {
2055                 rplci->Id = 0;
2056                 Info = 0x300A;
2057                 break;
2058               }
2059             }
2060             if(parms->length)
2061             {
2062               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2063               {
2064                 dbug(1,dprintf("format wrong"));
2065                 rplci->Id = 0;
2066                 Info = _WRONG_MESSAGE_FORMAT;
2067                 break;
2068               }
2069             }
2070             dummy.length = 0;
2071             dummy.info = "\x00";
2072             add_b1(rplci, &dummy, 0, 0);
2073             if (a->Info_Mask[appl->Id-1] & 0x200)
2074             {
2075               /* early B3 connect (CIP mask bit 9) no release after a disc */
2076               add_p(rplci,LLI,"\x01\x01");
2077             }
2078             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2079             sig_req(rplci,ASSIGN,DSIG_ID);
2080             send_req(rplci);
2081             add_s(rplci,CAI,&ss_parms[2]);
2082             rplci->command = RESUME_REQ;
2083             sig_req(rplci,RESUME,0);
2084             rplci->State = RESUMING;
2085             send_req(rplci);
2086             break;
2087
2088           case S_CONF_BEGIN: /* Request */
2089           case S_CONF_DROP:
2090           case S_CONF_ISOLATE:
2091           case S_CONF_REATTACH:
2092             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2093             {
2094               dbug(1,dprintf("format wrong"));
2095               Info = _WRONG_MESSAGE_FORMAT;
2096               break;
2097             }
2098             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2099             {
2100               d = GET_DWORD(ss_parms[2].info);     
2101               if(d>=0x80)
2102               {
2103                 dbug(1,dprintf("format wrong"));
2104                 Info = _WRONG_MESSAGE_FORMAT;
2105                 break;
2106               }
2107               plci->ptyState = (byte)SSreq;
2108               plci->command = 0;
2109               cai[0] = 2;
2110               switch(SSreq)
2111               {
2112               case S_CONF_BEGIN:
2113                   cai[1] = CONF_BEGIN;
2114                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2115                   break;
2116               case S_CONF_DROP:
2117                   cai[1] = CONF_DROP;
2118                   plci->internal_command = CONF_DROP_REQ_PEND;
2119                   break;
2120               case S_CONF_ISOLATE:
2121                   cai[1] = CONF_ISOLATE;
2122                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2123                   break;
2124               case S_CONF_REATTACH:
2125                   cai[1] = CONF_REATTACH;
2126                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2127                   break;
2128               }
2129               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2130               add_p(plci,CAI,cai);
2131               sig_req(plci,S_SERVICE,0);
2132               send_req(plci);
2133               return false;
2134             }
2135             else Info = 0x3010;                    /* wrong state           */
2136             break;
2137
2138           case S_ECT:
2139           case S_3PTY_BEGIN:
2140           case S_3PTY_END:
2141           case S_CONF_ADD:
2142             if(parms->length==7)
2143             {
2144               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2145               {
2146                 dbug(1,dprintf("format wrong"));
2147                 Info = _WRONG_MESSAGE_FORMAT;
2148                 break;
2149               }
2150             }
2151             else if(parms->length==8) /* workaround for the T-View-S */
2152             {
2153               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2154               {
2155                 dbug(1,dprintf("format wrong"));
2156                 Info = _WRONG_MESSAGE_FORMAT;
2157                 break;
2158               }
2159             }
2160             else
2161             {
2162               Info = _WRONG_MESSAGE_FORMAT;
2163               break;
2164             }
2165             if(!msg[1].length)
2166             {
2167               Info = _WRONG_MESSAGE_FORMAT;
2168               break;
2169             }
2170             if (!plci)
2171             {
2172               Info = _WRONG_IDENTIFIER;
2173               break;
2174             }
2175             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2176             relatedPLCIvalue &= 0x0000FFFF;
2177             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2178             /* controller starts with 0 up to (max_adapter - 1) */
2179             if (((relatedPLCIvalue & 0x7f) == 0)
2180              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2181              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2182             {
2183               if(SSreq==S_3PTY_END)
2184               {
2185                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2186                 rplci = plci;
2187               }
2188               else
2189               {
2190                 Info = 0x3010;                    /* wrong state           */
2191                 break;
2192               }
2193             }
2194             else
2195             {  
2196               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2197               relatedPLCIvalue >>=8;
2198               /* find PLCI PTR*/
2199               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2200               {
2201                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2202                 {
2203                   rplci = &relatedadapter->plci[i];
2204                 }
2205               }
2206               if(!rplci || !relatedPLCIvalue)
2207               {
2208                 if(SSreq==S_3PTY_END)
2209                 {
2210                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2211                   rplci = plci;
2212                 }
2213                 else
2214                 {
2215                   Info = 0x3010;                    /* wrong state           */
2216                   break;
2217                 }
2218               }
2219             }
2220 /*
2221             dbug(1,dprintf("rplci:%x",rplci));
2222             dbug(1,dprintf("plci:%x",plci));
2223             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2224             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2225             dbug(1,dprintf("SSreq:%x",SSreq));
2226             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2227             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2228             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2229 */
2230             /* send PTY/ECT req, cannot check all states because of US stuff */
2231             if( !rplci->internal_command && rplci->appl )
2232             {
2233               plci->command = 0;
2234               rplci->relatedPTYPLCI = plci;
2235               plci->relatedPTYPLCI = rplci;
2236               rplci->ptyState = (byte)SSreq;
2237               if(SSreq==S_ECT)
2238               {
2239                 rplci->internal_command = ECT_REQ_PEND;
2240                 cai[1] = ECT_EXECUTE;
2241
2242                 rplci->vswitchstate=0;
2243                 rplci->vsprot=0;
2244                 rplci->vsprotdialect=0;
2245                 plci->vswitchstate=0;
2246                 plci->vsprot=0;
2247                 plci->vsprotdialect=0;
2248
2249               }
2250               else if(SSreq==S_CONF_ADD)
2251               {
2252                 rplci->internal_command = CONF_ADD_REQ_PEND;
2253                 cai[1] = CONF_ADD;
2254               }
2255               else
2256               {
2257                 rplci->internal_command = PTY_REQ_PEND;
2258                 cai[1] = (byte)(SSreq-3);
2259               }
2260               rplci->number = Number;
2261               if(plci!=rplci) /* explicit invocation */
2262               {
2263                 cai[0] = 2;
2264                 cai[2] = plci->Sig.Id;
2265                 dbug(1,dprintf("explicit invocation"));
2266               }
2267               else
2268               {
2269                 dbug(1,dprintf("implicit invocation"));
2270                 cai[0] = 1;
2271               }
2272               add_p(rplci,CAI,cai);
2273               sig_req(rplci,S_SERVICE,0);
2274               send_req(rplci);
2275               return false;
2276             }
2277             else
2278             {
2279               dbug(0,dprintf("Wrong line"));
2280               Info = 0x3010;                    /* wrong state           */
2281               break;
2282             }
2283             break;
2284
2285           case S_CALL_DEFLECTION:
2286             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2287             {
2288               dbug(1,dprintf("format wrong"));
2289               Info = _WRONG_MESSAGE_FORMAT;
2290               break;
2291             }
2292             if (!plci)
2293             {
2294               Info = _WRONG_IDENTIFIER;
2295               break;
2296             }
2297             /* reuse unused screening indicator */
2298             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2299             plci->command = 0;
2300             plci->internal_command = CD_REQ_PEND;
2301             appl->CDEnable = true;
2302             cai[0] = 1;
2303             cai[1] = CALL_DEFLECTION;
2304             add_p(plci,CAI,cai);
2305             add_p(plci,CPN,ss_parms[3].info);
2306             sig_req(plci,S_SERVICE,0);
2307             send_req(plci);
2308             return false;
2309             break;
2310
2311           case S_CALL_FORWARDING_START:
2312             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2313             {
2314               dbug(1,dprintf("format wrong"));
2315               Info = _WRONG_MESSAGE_FORMAT;
2316               break;
2317             }
2318
2319             if((i=get_plci(a)))
2320             {
2321               rplci = &a->plci[i-1];
2322               rplci->appl = appl;
2323               add_p(rplci,CAI,"\x01\x80");
2324               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2325               sig_req(rplci,ASSIGN,DSIG_ID);
2326               send_req(rplci);
2327             }
2328             else
2329             {
2330               Info = _OUT_OF_PLCI;
2331               break;
2332             }
2333
2334             /* reuse unused screening indicator */
2335             rplci->internal_command = CF_START_PEND;
2336             rplci->appl = appl;
2337             rplci->number = Number;
2338             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2339             cai[0] = 2;
2340             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2341             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2342             add_p(rplci,CAI,cai);
2343             add_p(rplci,OAD,ss_parms[5].info);
2344             add_p(rplci,CPN,ss_parms[6].info);
2345             sig_req(rplci,S_SERVICE,0);
2346             send_req(rplci);
2347             return false;
2348             break;
2349
2350           case S_INTERROGATE_DIVERSION:
2351           case S_INTERROGATE_NUMBERS:
2352           case S_CALL_FORWARDING_STOP:
2353           case S_CCBS_REQUEST:
2354           case S_CCBS_DEACTIVATE:
2355           case S_CCBS_INTERROGATE:
2356             switch(SSreq)
2357             {
2358             case S_INTERROGATE_NUMBERS:
2359                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2360                 {
2361                   dbug(0,dprintf("format wrong"));
2362                   Info = _WRONG_MESSAGE_FORMAT;
2363                 }
2364                 break;
2365             case S_CCBS_REQUEST:
2366             case S_CCBS_DEACTIVATE:
2367                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2368                 {
2369                   dbug(0,dprintf("format wrong"));
2370                   Info = _WRONG_MESSAGE_FORMAT;
2371                 }
2372                 break;
2373             case S_CCBS_INTERROGATE:
2374                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2375                 {
2376                   dbug(0,dprintf("format wrong"));
2377                   Info = _WRONG_MESSAGE_FORMAT;
2378                 }
2379                 break;
2380             default:
2381             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2382             {
2383               dbug(0,dprintf("format wrong"));
2384               Info = _WRONG_MESSAGE_FORMAT;
2385               break;
2386             }
2387                 break;
2388             }
2389
2390             if(Info) break;
2391             if((i=get_plci(a)))
2392             {
2393               rplci = &a->plci[i-1];
2394               switch(SSreq)
2395               {
2396                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2397                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2398                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2399                   break;
2400                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2401                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2402                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2403                   break;
2404                 case S_CALL_FORWARDING_STOP:
2405                   rplci->internal_command = CF_STOP_PEND;
2406                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2407                   break;
2408                 case S_CCBS_REQUEST:
2409                   cai[1] = CCBS_REQUEST;
2410                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2411                   break;
2412                 case S_CCBS_DEACTIVATE:
2413                   cai[1] = CCBS_DEACTIVATE;
2414                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2415                   break;
2416                 case S_CCBS_INTERROGATE:
2417                   cai[1] = CCBS_INTERROGATE;
2418                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2419                   break;
2420                 default:
2421                   cai[1] = 0;
2422                 break;
2423               }
2424               rplci->appl = appl;
2425               rplci->number = Number;
2426               add_p(rplci,CAI,"\x01\x80");
2427               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2428               sig_req(rplci,ASSIGN,DSIG_ID);
2429               send_req(rplci);
2430             }
2431             else
2432             {
2433               Info = _OUT_OF_PLCI;
2434               break;
2435             }
2436
2437             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2438             switch(SSreq)
2439             {
2440             case S_INTERROGATE_NUMBERS:
2441                 cai[0] = 1;
2442                 add_p(rplci,CAI,cai);
2443                 break;
2444             case S_CCBS_REQUEST:
2445             case S_CCBS_DEACTIVATE:
2446                 cai[0] = 3;
2447                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2448                 add_p(rplci,CAI,cai);
2449                 break;
2450             case S_CCBS_INTERROGATE:
2451                 cai[0] = 3;
2452                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2453                 add_p(rplci,CAI,cai);
2454                 add_p(rplci,OAD,ss_parms[4].info);
2455                 break;
2456             default:
2457             cai[0] = 2;
2458             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2459             add_p(rplci,CAI,cai);
2460             add_p(rplci,OAD,ss_parms[5].info);
2461                 break;
2462             }
2463                         
2464             sig_req(rplci,S_SERVICE,0);
2465             send_req(rplci);
2466             return false;
2467             break;
2468
2469           case S_MWI_ACTIVATE:
2470             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2471             {
2472               dbug(1,dprintf("format wrong"));
2473               Info = _WRONG_MESSAGE_FORMAT;
2474               break;
2475             }
2476             if(!plci)
2477             {                               
2478               if((i=get_plci(a)))
2479               {
2480                 rplci = &a->plci[i-1];
2481                 rplci->appl = appl;
2482                 rplci->cr_enquiry=true;
2483                 add_p(rplci,CAI,"\x01\x80");
2484                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2485                 sig_req(rplci,ASSIGN,DSIG_ID);
2486                 send_req(rplci);
2487               }
2488               else
2489               {
2490                 Info = _OUT_OF_PLCI;
2491                 break;
2492               }
2493             }
2494             else
2495             {
2496               rplci = plci;
2497               rplci->cr_enquiry=false;
2498             }
2499
2500             rplci->command = 0;
2501             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2502             rplci->appl = appl;
2503             rplci->number = Number;
2504
2505             cai[0] = 13;
2506             cai[1] = ACTIVATION_MWI; /* Function */
2507             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2508             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2509             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2510             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2511             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2512             add_p(rplci,CAI,cai);
2513             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2514             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2515             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2516             add_p(rplci,UID,ss_parms[10].info); /* Time */
2517             sig_req(rplci,S_SERVICE,0);
2518             send_req(rplci);
2519             return false;
2520
2521           case S_MWI_DEACTIVATE:
2522             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2523             {
2524               dbug(1,dprintf("format wrong"));
2525               Info = _WRONG_MESSAGE_FORMAT;
2526               break;
2527             }
2528             if(!plci)
2529             {                               
2530               if((i=get_plci(a)))
2531               {
2532                 rplci = &a->plci[i-1];
2533                 rplci->appl = appl;
2534                 rplci->cr_enquiry=true;
2535                 add_p(rplci,CAI,"\x01\x80");
2536                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2537                 sig_req(rplci,ASSIGN,DSIG_ID);
2538                 send_req(rplci);
2539               }
2540               else
2541               {
2542                 Info = _OUT_OF_PLCI;
2543                 break;
2544               }
2545             }
2546             else
2547             {
2548               rplci = plci;
2549               rplci->cr_enquiry=false;
2550             }
2551
2552             rplci->command = 0;
2553             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2554             rplci->appl = appl;
2555             rplci->number = Number;
2556
2557             cai[0] = 5;
2558             cai[1] = DEACTIVATION_MWI; /* Function */
2559             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2560             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2561             add_p(rplci,CAI,cai);
2562             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2563             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2564             sig_req(rplci,S_SERVICE,0);
2565             send_req(rplci);
2566             return false;
2567
2568           default:
2569             Info = 0x300E;  /* not supported */
2570             break;
2571         }
2572         break; /* case SELECTOR_SU_SERV: end */
2573
2574
2575       case SELECTOR_DTMF:
2576         return (dtmf_request (Id, Number, a, plci, appl, msg));
2577
2578
2579
2580       case SELECTOR_LINE_INTERCONNECT:
2581         return (mixer_request (Id, Number, a, plci, appl, msg));
2582
2583
2584
2585       case PRIV_SELECTOR_ECHO_CANCELLER:
2586         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2587         return (ec_request (Id, Number, a, plci, appl, msg));
2588
2589       case SELECTOR_ECHO_CANCELLER:
2590         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2591         return (ec_request (Id, Number, a, plci, appl, msg));
2592
2593
2594       case SELECTOR_V42BIS:
2595       default:
2596         Info = _FACILITY_NOT_SUPPORTED;
2597         break;
2598     } /* end of switch(selector) */
2599   }
2600
2601   dbug(1,dprintf("SendFacRc"));
2602   sendf(appl,
2603         _FACILITY_R|CONFIRM,
2604         Id,
2605         Number,
2606         "wws",Info,selector,SSparms);
2607   return false;
2608 }
2609
2610 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2611                          PLCI *plci, APPL *appl, API_PARSE *msg)
2612 {
2613   dbug(1,dprintf("facility_res"));
2614   return false;
2615 }
2616
2617 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2618                            PLCI *plci, APPL *appl, API_PARSE *parms)
2619 {
2620   word Info = 0;
2621   byte req;
2622   byte len;
2623   word w;
2624   word fax_control_bits, fax_feature_bits, fax_info_change;
2625   API_PARSE * ncpi;
2626     byte pvc[2];
2627
2628     API_PARSE fax_parms[9];
2629   word i;
2630
2631
2632   dbug(1,dprintf("connect_b3_req"));
2633   if(plci)
2634   {
2635     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2636      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2637     {
2638       Info = _WRONG_STATE;
2639     }
2640     else
2641     {
2642       /* local reply if assign unsuccessfull
2643          or B3 protocol allows only one layer 3 connection
2644            and already connected
2645              or B2 protocol not any LAPD
2646                and connect_b3_req contradicts originate/answer direction */
2647       if (!plci->NL.Id
2648        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2649         && ((plci->channels != 0)
2650          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2651           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2652       {
2653         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2654                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2655         Info = _WRONG_STATE;
2656         sendf(appl,                                                        
2657               _CONNECT_B3_R|CONFIRM,
2658               Id,
2659               Number,
2660               "w",Info);
2661         return false;
2662       }
2663       plci->requested_options_conn = 0;
2664
2665       req = N_CONNECT;
2666       ncpi = &parms[0];
2667       if(plci->B3_prot==2 || plci->B3_prot==3)
2668       {
2669         if(ncpi->length>2)
2670         {
2671           /* check for PVC */
2672           if(ncpi->info[2] || ncpi->info[3])
2673           {
2674             pvc[0] = ncpi->info[3];
2675             pvc[1] = ncpi->info[2];
2676             add_d(plci,2,pvc);
2677             req = N_RESET;
2678           }
2679           else
2680           {
2681             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2682             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2683           }
2684         }
2685       }
2686       else if(plci->B3_prot==5)
2687       {
2688         if (plci->NL.Id && !plci->nl_remove_id)
2689         {
2690           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2691           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2692           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2693            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2694           {
2695             len = offsetof(T30_INFO, universal_6);
2696             fax_info_change = false;
2697             if (ncpi->length >= 4)
2698             {
2699               w = GET_WORD(&ncpi->info[3]);
2700               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2701               {
2702                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2703                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2704                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2705                 fax_info_change = true;
2706               }
2707               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2708               if (w & 0x0002)  /* Fax-polling request */
2709                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2710               if ((w & 0x0004) /* Request to send / poll another document */
2711                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2712               {
2713                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2714               }
2715               if (ncpi->length >= 6)
2716               {
2717                 w = GET_WORD(&ncpi->info[5]);
2718                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2719                 {
2720                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2721                   fax_info_change = true;
2722                 }
2723
2724                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2725                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2726                 {
2727                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2728                 }
2729                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2730                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2731                 {
2732                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2733                 }
2734                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2735                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2736                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2737                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2738                 {
2739                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2740                     Info = _WRONG_MESSAGE_FORMAT;
2741                   else
2742                   {
2743                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2744                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2745       {
2746                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2747                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2748                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2749       }
2750                     w = fax_parms[4].length;
2751                     if (w > 20)
2752                       w = 20;
2753                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2754                     for (i = 0; i < w; i++)
2755                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2756                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2757                     len = offsetof(T30_INFO, station_id) + 20;
2758                     w = fax_parms[5].length;
2759                     if (w > 20)
2760                       w = 20;
2761                     plci->fax_connect_info_buffer[len++] = (byte) w;
2762                     for (i = 0; i < w; i++)
2763                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2764                     w = fax_parms[6].length;
2765                     if (w > 20)
2766                       w = 20;
2767                     plci->fax_connect_info_buffer[len++] = (byte) w;
2768                     for (i = 0; i < w; i++)
2769                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2770                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2771                       & (1L << PRIVATE_FAX_NONSTANDARD))
2772       {
2773                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2774         {
2775                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2776                         plci->fax_connect_info_buffer[len++] = 0;
2777         }
2778                       else
2779                       {
2780           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2781             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2782    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2783           for (i = 0; i < fax_parms[7].length; i++)
2784      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2785                       }
2786                     }
2787                   }
2788                 }
2789                 else
2790                 {
2791                   len = offsetof(T30_INFO, universal_6);
2792                 }
2793                 fax_info_change = true;
2794
2795               }
2796               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2797               {
2798                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2799                 fax_info_change = true;
2800               }
2801             }
2802             if (Info == GOOD)
2803             {
2804               plci->fax_connect_info_length = len;
2805               if (fax_info_change)
2806               {
2807                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2808                 {
2809                   start_internal_command (Id, plci, fax_connect_info_command);
2810                   return false;
2811                 }
2812                 else
2813                 {
2814                   start_internal_command (Id, plci, fax_adjust_b23_command);
2815                   return false;
2816                 }
2817               }
2818             }
2819           }
2820           else  Info = _WRONG_STATE;
2821         }
2822         else  Info = _WRONG_STATE;
2823       }
2824
2825       else if (plci->B3_prot == B3_RTP)
2826       {
2827         plci->internal_req_buffer[0] = ncpi->length + 1;
2828         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2829         for (w = 0; w < ncpi->length; w++)
2830           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2831         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2832         return false;
2833       }
2834
2835       if(!Info)
2836       {
2837         nl_req_ncci(plci,req,0);
2838         return 1;
2839       }
2840     }
2841   }
2842   else Info = _WRONG_IDENTIFIER;
2843
2844   sendf(appl,
2845         _CONNECT_B3_R|CONFIRM,
2846         Id,
2847         Number,
2848         "w",Info);
2849   return false;
2850 }
2851
2852 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2853                            PLCI *plci, APPL *appl, API_PARSE *parms)
2854 {
2855   word ncci;
2856   API_PARSE * ncpi;
2857   byte req;
2858
2859   word w;
2860
2861
2862     API_PARSE fax_parms[9];
2863   word i;
2864   byte len;
2865
2866
2867   dbug(1,dprintf("connect_b3_res"));
2868
2869   ncci = (word)(Id>>16);
2870   if(plci && ncci) {
2871     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2872       if (GET_WORD (&parms[0].info[0]) != 0)
2873       {
2874         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2875         channel_request_xon (plci, a->ncci_ch[ncci]);
2876         channel_xmit_xon (plci);
2877         cleanup_ncci_data (plci, ncci);
2878         nl_req_ncci(plci,N_DISC,(byte)ncci);
2879         return 1;
2880       }
2881       a->ncci_state[ncci] = INC_ACT_PENDING;
2882
2883       req = N_CONNECT_ACK;
2884       ncpi = &parms[1];
2885       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2886       {
2887
2888         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2889           & (1L << PRIVATE_FAX_NONSTANDARD))
2890  {
2891    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2892     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2893     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2894    {
2895             len = offsetof(T30_INFO, station_id) + 20;
2896             if (plci->fax_connect_info_length < len)
2897             {
2898               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2899               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2900             }
2901             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2902             {
2903               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2904             }
2905             else
2906             {
2907               if (plci->fax_connect_info_length <= len)
2908                 plci->fax_connect_info_buffer[len] = 0;
2909               len += 1 + plci->fax_connect_info_buffer[len];
2910               if (plci->fax_connect_info_length <= len)
2911                 plci->fax_connect_info_buffer[len] = 0;
2912               len += 1 + plci->fax_connect_info_buffer[len];
2913               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2914                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2915               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2916               for (i = 0; i < fax_parms[7].length; i++)
2917                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2918             }
2919             plci->fax_connect_info_length = len;
2920             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2921             start_internal_command (Id, plci, fax_connect_ack_command);
2922      return false;
2923           }
2924         }
2925
2926         nl_req_ncci(plci,req,(byte)ncci);
2927         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2928          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2929         {
2930           if (plci->B3_prot == 4)
2931             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2932           else
2933             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2934           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2935         }
2936       }
2937
2938       else if (plci->B3_prot == B3_RTP)
2939       {
2940         plci->internal_req_buffer[0] = ncpi->length + 1;
2941         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2942         for (w = 0; w < ncpi->length; w++)
2943           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2944         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2945         return false;
2946       }
2947
2948       else
2949       {
2950         if(ncpi->length>2) {
2951           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2952           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2953         }
2954         nl_req_ncci(plci,req,(byte)ncci);
2955         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2956         if (plci->adjust_b_restore)
2957         {
2958           plci->adjust_b_restore = false;
2959           start_internal_command (Id, plci, adjust_b_restore);
2960         }
2961       }
2962       return 1;
2963     }
2964   }
2965   return false;
2966 }
2967
2968 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2969                              PLCI *plci, APPL *appl, API_PARSE *parms)
2970 {
2971   word ncci;
2972
2973   ncci = (word)(Id>>16);
2974   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2975
2976   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2977    && (plci->State != OUTG_DIS_PENDING))
2978   {
2979     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2980       a->ncci_state[ncci] = CONNECTED;
2981       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2982       channel_request_xon (plci, a->ncci_ch[ncci]);
2983       channel_xmit_xon (plci);
2984     }
2985   }
2986   return false;
2987 }
2988
2989 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2990                               PLCI *plci, APPL *appl, API_PARSE *parms)
2991 {
2992   word Info;
2993   word ncci;
2994   API_PARSE * ncpi;
2995
2996   dbug(1,dprintf("disconnect_b3_req"));
2997
2998   Info = _WRONG_IDENTIFIER;
2999   ncci = (word)(Id>>16);
3000   if (plci && ncci)
3001   {
3002     Info = _WRONG_STATE;
3003     if ((a->ncci_state[ncci] == CONNECTED)
3004      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3005      || (a->ncci_state[ncci] == INC_CON_PENDING)
3006      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3007     {
3008       a->ncci_state[ncci] = OUTG_DIS_PENDING;
3009       channel_request_xon (plci, a->ncci_ch[ncci]);
3010       channel_xmit_xon (plci);
3011
3012       if (a->ncci[ncci].data_pending
3013        && ((plci->B3_prot == B3_TRANSPARENT)
3014         || (plci->B3_prot == B3_T30)
3015         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3016       {
3017         plci->send_disc = (byte)ncci;
3018         plci->command = 0;
3019         return false;
3020       }
3021       else
3022       {
3023         cleanup_ncci_data (plci, ncci);
3024
3025         if(plci->B3_prot==2 || plci->B3_prot==3)
3026         {
3027           ncpi = &parms[0];
3028           if(ncpi->length>3)
3029           {
3030             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3031           }
3032         }
3033         nl_req_ncci(plci,N_DISC,(byte)ncci);
3034       }
3035       return 1;
3036     }
3037   }
3038   sendf(appl,
3039         _DISCONNECT_B3_R|CONFIRM,
3040         Id,
3041         Number,
3042         "w",Info);
3043   return false;
3044 }
3045
3046 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3047                               PLCI *plci, APPL *appl, API_PARSE *parms)
3048 {
3049   word ncci;
3050   word i;
3051
3052   ncci = (word)(Id>>16);
3053   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3054   if(plci && ncci) {
3055     plci->requested_options_conn = 0;
3056     plci->fax_connect_info_length = 0;
3057     plci->ncpi_state = 0x00;
3058     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3059       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3060     {
3061       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3062     }
3063     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3064     if(i<MAX_CHANNELS_PER_PLCI) {
3065       if(plci->channels)plci->channels--;
3066       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3067       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3068
3069       ncci_free_receive_buffers (plci, ncci);
3070
3071       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3072         if(plci->State == SUSPENDING){
3073           sendf(plci->appl,
3074                 _FACILITY_I,
3075                 Id & 0xffffL,
3076                 0,
3077                 "ws", (word)3, "\x03\x04\x00\x00");
3078           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3079         }
3080         plci_remove(plci);
3081         plci->State=IDLE;
3082       }
3083     }
3084     else
3085     {
3086       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3087        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3088        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3089       {
3090         ncci_free_receive_buffers (plci, ncci);
3091
3092         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3093
3094         plci->adapter->ncci_state[ncci] = IDLE;
3095         start_internal_command (Id, plci, fax_disconnect_command);
3096         return 1;
3097       }
3098     }
3099   }
3100   return false;
3101 }
3102
3103 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3104                         PLCI *plci, APPL *appl, API_PARSE *parms)
3105 {
3106   NCCI   *ncci_ptr;
3107   DATA_B3_DESC   *data;
3108   word Info;
3109   word ncci;
3110   word i;
3111
3112   dbug(1,dprintf("data_b3_req"));
3113
3114   Info = _WRONG_IDENTIFIER;
3115   ncci = (word)(Id>>16);
3116   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3117
3118   if (plci && ncci)
3119   {
3120     Info = _WRONG_STATE;
3121     if ((a->ncci_state[ncci] == CONNECTED)
3122      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3123     {
3124         /* queue data */
3125       ncci_ptr = &(a->ncci[ncci]);
3126       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3127       if (i >= MAX_DATA_B3)
3128         i -= MAX_DATA_B3;
3129       data = &(ncci_ptr->DBuffer[i]);
3130       data->Number = Number;
3131       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3132        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3133       {
3134
3135         data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3136
3137       }
3138       else
3139         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3140       data->Length = GET_WORD(parms[1].info);
3141       data->Handle = GET_WORD(parms[2].info);
3142       data->Flags = GET_WORD(parms[3].info);
3143       (ncci_ptr->data_pending)++;
3144
3145         /* check for delivery confirmation */
3146       if (data->Flags & 0x0004)
3147       {
3148         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3149         if (i >= MAX_DATA_ACK)
3150           i -= MAX_DATA_ACK;
3151         ncci_ptr->DataAck[i].Number = data->Number;
3152         ncci_ptr->DataAck[i].Handle = data->Handle;
3153         (ncci_ptr->data_ack_pending)++;
3154       }
3155
3156       send_data(plci);
3157       return false;
3158     }
3159   }
3160   if (appl)
3161   {
3162     if (plci)
3163     {
3164       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3165        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3166       {
3167
3168         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3169
3170       }
3171     }
3172     sendf(appl,
3173           _DATA_B3_R|CONFIRM,
3174           Id,
3175           Number,
3176           "ww",GET_WORD(parms[2].info),Info);
3177   }
3178   return false;
3179 }
3180
3181 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3182                         PLCI *plci, APPL *appl, API_PARSE *parms)
3183 {
3184   word n;
3185   word ncci;
3186   word NCCIcode;
3187
3188   dbug(1,dprintf("data_b3_res"));
3189
3190   ncci = (word)(Id>>16);
3191   if(plci && ncci) {
3192     n = GET_WORD(parms[0].info);
3193     dbug(1,dprintf("free(%d)",n));
3194     NCCIcode = ncci | (((word) a->Id) << 8);
3195     if(n<appl->MaxBuffer &&
3196        appl->DataNCCI[n]==NCCIcode &&
3197        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3198       dbug(1,dprintf("found"));
3199       appl->DataNCCI[n] = 0;
3200
3201       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3202<