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