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