GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / isdn / hardware / eicon / message.c
blobc23da1293965962c8b92222ad23461649814ac39
1 /*
3 Copyright (c) Eicon Networks, 2002.
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
8 Eicon File Revision : 2.1
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.
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.
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.
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"
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
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;
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
65 CAPI can request to process all return codes self only if:
66 protocol code supports this && xdi supports this
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))
70 /*------------------------------------------------------------------*/
71 /* local function prototypes */
72 /*------------------------------------------------------------------*/
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);
86 word api_remove_start(void);
87 void api_remove_complete(void);
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 *);
93 void callback(ENTITY *);
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);
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
105 static void nl_ind(PLCI *);
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 *);
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);
156 XON protocol helpers
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);
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);
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);
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);
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);
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);
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);
220 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor (PLCI *plci, int nr);
223 /*------------------------------------------------------------------*/
224 /* external function prototypes */
225 /*------------------------------------------------------------------*/
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)))
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);
238 int fax_head_line_time (char *buffer);
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;
255 static byte remove_started = false;
256 static PLCI dummy_plci;
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}
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 */
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 */
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 */
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 */
358 /*------------------------------------------------------------------*/
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)
367 static byte v120_default_header[] =
370 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
374 static byte v120_break_header[] =
377 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
382 /*------------------------------------------------------------------*/
383 /* API_PUT function */
384 /*------------------------------------------------------------------*/
386 word api_put(APPL * appl, CAPI_MSG * msg)
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];
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;
405 controller = (byte)((msg->header.controller &0x7f)-1);
407 /* controller starts with 0 up to (max_adapter - 1) */
408 if ( controller >= max_adapter )
410 dbug(1,dprintf("invalid ctrl"));
411 return _BAD_MSG;
414 a = &adapter[controller];
415 plci = NULL;
416 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
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))))
430 i = plci->msg_in_read_pos;
431 j = plci->msg_in_write_pos;
432 if (j >= i)
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;
439 else
442 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
444 if (i > MSG_IN_QUEUE_SIZE - n)
445 i = MSG_IN_QUEUE_SIZE - n + 1;
446 i -= j;
449 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
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));
456 return _QUEUE_FULL;
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)))
462 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463 c = true;
465 if (msg->header.command == _DATA_B3_R)
467 if (msg->header.length < 20)
469 dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470 return _BAD_MSG;
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)
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))
483 n++;
484 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485 l++;
488 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489 MSG_IN_OVERHEAD + 3) & 0xfffc;
492 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
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));
497 return _QUEUE_FULL;
499 if (plci->req_in || plci->internal_command)
501 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
504 dbug(0,dprintf("Q-FULL3(requeue)"));
506 return _QUEUE_FULL;
508 c = true;
511 else
513 if (plci->req_in || plci->internal_command)
514 c = true;
515 else
517 plci->command = msg->header.command;
518 plci->number = msg->header.number;
521 if (c)
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)
535 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
539 j = (j + 3) & 0xfffc;
541 *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543 return 0;
546 else
548 plci = NULL;
551 dbug(1,dprintf("com=%x",msg->header.command));
553 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554 for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
556 if(ftable[i].command==msg->header.command) {
557 /* break loop if the message is correct, otherwise continue scan */
558 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
559 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
560 ret = 0;
561 break;
563 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
566 if(ret) {
567 dbug(1,dprintf("BAD_MSG"));
568 if(plci) plci->command = 0;
569 return ret;
573 c = ftable[i].function(GET_DWORD(&msg->header.controller),
574 msg->header.number,
576 plci,
577 appl,
578 msg_parms);
580 channel_xmit_extended_xon (plci);
582 if(c==1) send_req(plci);
583 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584 if(plci && !plci->req_in) plci->command = 0;
585 return 0;
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages */
591 /*------------------------------------------------------------------*/
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
595 word i;
596 word p;
598 for(i=0,p=0; format[i]; i++) {
599 if(parms)
601 parms[i].info = &msg[p];
603 switch(format[i]) {
604 case 'b':
605 p +=1;
606 break;
607 case 'w':
608 p +=2;
609 break;
610 case 'd':
611 p +=4;
612 break;
613 case 's':
614 if(msg[p]==0xff) {
615 parms[i].info +=2;
616 parms[i].length = msg[p+1] + (msg[p+2]<<8);
617 p +=(parms[i].length +3);
619 else {
620 parms[i].length = msg[p];
621 p +=(parms[i].length +1);
623 break;
626 if(p>length) return true;
628 if(parms) parms[i].info = NULL;
629 return false;
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
634 word i, j, n = 0;
635 byte *p;
637 p = out->info;
638 for (i = 0; format[i] != '\0'; i++)
640 out->parms[i].info = p;
641 out->parms[i].length = in[i].length;
642 switch (format[i])
644 case 'b':
645 n = 1;
646 break;
647 case 'w':
648 n = 2;
649 break;
650 case 'd':
651 n = 4;
652 break;
653 case 's':
654 n = in[i].length + 1;
655 break;
657 for (j = 0; j < n; j++)
658 *(p++) = in[i].info[j];
660 out->parms[i].info = NULL;
661 out->parms[i].length = 0;
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
666 word i;
668 i = 0;
671 out[i].info = in->parms[i].info;
672 out[i].length = in->parms[i].length;
673 } while (in->parms[i++].info);
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function */
679 /*------------------------------------------------------------------*/
681 word api_remove_start(void)
683 word i;
684 word j;
686 if(!remove_started) {
687 remove_started = true;
688 for(i=0;i<max_adapter;i++) {
689 if(adapter[i].request) {
690 for(j=0;j<adapter[i].max_plci;j++) {
691 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
695 return 1;
697 else {
698 for(i=0;i<max_adapter;i++) {
699 if(adapter[i].request) {
700 for(j=0;j<adapter[i].max_plci;j++) {
701 if(adapter[i].plci[j].Sig.Id) return 1;
706 api_remove_complete();
707 return 0;
711 /*------------------------------------------------------------------*/
712 /* internal command queue */
713 /*------------------------------------------------------------------*/
715 static void init_internal_command_queue (PLCI *plci)
717 word i;
719 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
720 (char *)(FILE_), __LINE__));
722 plci->internal_command = 0;
723 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724 plci->internal_command_queue[i] = NULL;
728 static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
730 word i;
732 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
733 UnMapId (Id), (char *)(FILE_), __LINE__));
735 if (plci->internal_command == 0)
737 plci->internal_command_queue[0] = command_function;
738 (* command_function)(Id, plci, OK);
740 else
742 i = 1;
743 while (plci->internal_command_queue[i] != NULL)
744 i++;
745 plci->internal_command_queue[i] = command_function;
750 static void next_internal_command (dword Id, PLCI *plci)
752 word i;
754 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
755 UnMapId (Id), (char *)(FILE_), __LINE__));
757 plci->internal_command = 0;
758 plci->internal_command_queue[0] = NULL;
759 while (plci->internal_command_queue[1] != NULL)
761 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
763 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764 (*(plci->internal_command_queue[0]))(Id, plci, OK);
765 if (plci->internal_command != 0)
766 return;
767 plci->internal_command_queue[0] = NULL;
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function */
774 /*------------------------------------------------------------------*/
776 static dword ncci_mapping_bug = 0;
778 static word get_ncci (PLCI *plci, byte ch, word force_ncci)
780 DIVA_CAPI_ADAPTER *a;
781 word ncci, i, j, k;
783 a = plci->adapter;
784 if (!ch || a->ch_ncci[ch])
786 ncci_mapping_bug++;
787 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789 ncci = ch;
791 else
793 if (force_ncci)
794 ncci = force_ncci;
795 else
797 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
798 ncci = ch;
799 else
801 ncci = 1;
802 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
803 ncci++;
804 if (ncci == MAX_NCCI+1)
806 ncci_mapping_bug++;
807 i = 1;
810 j = 1;
811 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
812 j++;
813 k = j;
814 if (j < MAX_NCCI+1)
818 j++;
819 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
821 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
822 if (i < MAX_NL_CHANNEL+1)
824 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825 ncci_mapping_bug, ch, force_ncci, i, k, j));
827 else
829 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
830 ncci_mapping_bug, ch, force_ncci));
832 ncci = ch;
835 a->ncci_plci[ncci] = plci->Id;
836 a->ncci_state[ncci] = IDLE;
837 if (!plci->ncci_ring_list)
838 plci->ncci_ring_list = ncci;
839 else
840 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
843 a->ncci_ch[ncci] = ch;
844 a->ch_ncci[ch] = (byte) ncci;
845 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846 ncci_mapping_bug, ch, force_ncci, ch, ncci));
848 return (ncci);
852 static void ncci_free_receive_buffers (PLCI *plci, word ncci)
854 DIVA_CAPI_ADAPTER *a;
855 APPL *appl;
856 word i, ncci_code;
857 dword Id;
859 a = plci->adapter;
860 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861 if (ncci)
863 if (a->ncci_plci[ncci] == plci->Id)
865 if (!plci->appl)
867 ncci_mapping_bug++;
868 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
869 ncci_mapping_bug, Id));
871 else
873 appl = plci->appl;
874 ncci_code = ncci | (((word) a->Id) << 8);
875 for (i = 0; i < appl->MaxBuffer; i++)
877 if ((appl->DataNCCI[i] == ncci_code)
878 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
880 appl->DataNCCI[i] = 0;
886 else
888 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
890 if (a->ncci_plci[ncci] == plci->Id)
892 if (!plci->appl)
894 ncci_mapping_bug++;
895 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
896 ncci_mapping_bug, Id));
898 else
900 appl = plci->appl;
901 ncci_code = ncci | (((word) a->Id) << 8);
902 for (i = 0; i < appl->MaxBuffer; i++)
904 if ((appl->DataNCCI[i] == ncci_code)
905 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
907 appl->DataNCCI[i] = 0;
917 static void cleanup_ncci_data (PLCI *plci, word ncci)
919 NCCI *ncci_ptr;
921 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
923 ncci_ptr = &(plci->adapter->ncci[ncci]);
924 if (plci->appl)
926 while (ncci_ptr->data_pending != 0)
928 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930 (ncci_ptr->data_out)++;
931 if (ncci_ptr->data_out == MAX_DATA_B3)
932 ncci_ptr->data_out = 0;
933 (ncci_ptr->data_pending)--;
936 ncci_ptr->data_out = 0;
937 ncci_ptr->data_pending = 0;
938 ncci_ptr->data_ack_out = 0;
939 ncci_ptr->data_ack_pending = 0;
944 static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
946 DIVA_CAPI_ADAPTER *a;
947 dword Id;
948 word i;
950 a = plci->adapter;
951 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952 if (!preserve_ncci)
953 ncci_free_receive_buffers (plci, ncci);
954 if (ncci)
956 if (a->ncci_plci[ncci] != plci->Id)
958 ncci_mapping_bug++;
959 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960 ncci_mapping_bug, Id, preserve_ncci));
962 else
964 cleanup_ncci_data (plci, ncci);
965 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967 a->ch_ncci[a->ncci_ch[ncci]] = 0;
968 if (!preserve_ncci)
970 a->ncci_ch[ncci] = 0;
971 a->ncci_plci[ncci] = 0;
972 a->ncci_state[ncci] = IDLE;
973 i = plci->ncci_ring_list;
974 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975 i = a->ncci_next[i];
976 if ((i != 0) && (a->ncci_next[i] == ncci))
978 if (i == ncci)
979 plci->ncci_ring_list = 0;
980 else if (plci->ncci_ring_list == ncci)
981 plci->ncci_ring_list = i;
982 a->ncci_next[i] = a->ncci_next[ncci];
984 a->ncci_next[ncci] = 0;
988 else
990 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
992 if (a->ncci_plci[ncci] == plci->Id)
994 cleanup_ncci_data (plci, ncci);
995 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997 a->ch_ncci[a->ncci_ch[ncci]] = 0;
998 if (!preserve_ncci)
1000 a->ncci_ch[ncci] = 0;
1001 a->ncci_plci[ncci] = 0;
1002 a->ncci_state[ncci] = IDLE;
1003 a->ncci_next[ncci] = 0;
1007 if (!preserve_ncci)
1008 plci->ncci_ring_list = 0;
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function */
1015 /*------------------------------------------------------------------*/
1017 static void plci_free_msg_in_queue (PLCI *plci)
1019 word i;
1021 if (plci->appl)
1023 i = plci->msg_in_read_pos;
1024 while (i != plci->msg_in_write_pos)
1026 if (i == plci->msg_in_wrap_pos)
1027 i = 0;
1028 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031 TransmitBufferFree (plci->appl,
1032 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1036 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037 MSG_IN_OVERHEAD + 3) & 0xfffc;
1041 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1047 static void plci_remove(PLCI * plci)
1050 if(!plci) {
1051 dbug(1,dprintf("plci_remove(no plci)"));
1052 return;
1054 init_internal_command_queue (plci);
1055 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1056 if(plci_remove_check(plci))
1058 return;
1060 if (plci->Sig.Id == 0xff)
1062 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063 if (plci->NL.Id && !plci->nl_remove_id)
1065 nl_req_ncci(plci,REMOVE,0);
1066 send_req(plci);
1069 else
1071 if (!plci->sig_remove_id
1072 && (plci->Sig.Id
1073 || (plci->req_in!=plci->req_out)
1074 || (plci->nl_req || plci->sig_req)))
1076 sig_req(plci,HANGUP,0);
1077 send_req(plci);
1080 ncci_remove (plci, 0, false);
1081 plci_free_msg_in_queue (plci);
1083 plci->channels = 0;
1084 plci->appl = NULL;
1085 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086 plci->State = OUTG_DIS_PENDING;
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers */
1091 /*------------------------------------------------------------------*/
1093 static void set_group_ind_mask (PLCI *plci)
1095 word i;
1097 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098 plci->group_optimization_mask_table[i] = 0xffffffffL;
1101 static void clear_group_ind_mask_bit (PLCI *plci, word b)
1103 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106 static byte test_group_ind_mask_bit (PLCI *plci, word b)
1108 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL */
1113 /*------------------------------------------------------------------*/
1115 static void clear_c_ind_mask (PLCI *plci)
1117 word i;
1119 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120 plci->c_ind_mask_table[i] = 0;
1123 static byte c_ind_mask_empty (PLCI *plci)
1125 word i;
1127 i = 0;
1128 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129 i++;
1130 return (i == C_IND_MASK_DWORDS);
1133 static void set_c_ind_mask_bit (PLCI *plci, word b)
1135 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138 static void clear_c_ind_mask_bit (PLCI *plci, word b)
1140 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143 static byte test_c_ind_mask_bit (PLCI *plci, word b)
1145 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148 static void dump_c_ind_mask (PLCI *plci)
1150 static char hex_digit_table[0x10] =
1151 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1152 word i, j, k;
1153 dword d;
1154 char *p;
1155 char buf[40];
1157 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1159 p = buf + 36;
1160 *p = '\0';
1161 for (j = 0; j < 4; j++)
1163 if (i+j < C_IND_MASK_DWORDS)
1165 d = plci->c_ind_mask_table[i+j];
1166 for (k = 0; k < 8; k++)
1168 *(--p) = hex_digit_table[d & 0xf];
1169 d >>= 4;
1172 else if (i != 0)
1174 for (k = 0; k < 8; k++)
1175 *(--p) = ' ';
1177 *(--p) = ' ';
1179 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1187 #define dump_plcis(a)
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message */
1193 /*------------------------------------------------------------------*/
1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196 PLCI *plci, APPL *appl, API_PARSE *parms)
1198 word ch;
1199 word i;
1200 word Info;
1201 word CIP;
1202 byte LinkLayer;
1203 API_PARSE * ai;
1204 API_PARSE * bp;
1205 API_PARSE ai_parms[5];
1206 word channel = 0;
1207 dword ch_mask;
1208 byte m;
1209 static byte esc_chi[35] = {0x02,0x18,0x01};
1210 static byte lli[2] = {0x01,0x00};
1211 byte noCh = 0;
1212 word dir = 0;
1213 byte *p_chi = "";
1215 for(i=0;i<5;i++) ai_parms[i].length = 0;
1217 dbug(1,dprintf("connect_req(%d)",parms->length));
1218 Info = _WRONG_IDENTIFIER;
1219 if(a)
1221 if(a->adapter_disabled)
1223 dbug(1,dprintf("adapter disabled"));
1224 Id = ((word)1<<8)|a->Id;
1225 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1226 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1227 return false;
1229 Info = _OUT_OF_PLCI;
1230 if((i=get_plci(a)))
1232 Info = 0;
1233 plci = &a->plci[i-1];
1234 plci->appl = appl;
1235 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1236 /* check 'external controller' bit for codec support */
1237 if(Id & EXT_CONTROLLER)
1239 if(AdvCodecSupport(a, plci, appl, 0) )
1241 plci->Id = 0;
1242 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1243 return 2;
1246 ai = &parms[9];
1247 bp = &parms[5];
1248 ch = 0;
1249 if(bp->length)LinkLayer = bp->info[3];
1250 else LinkLayer = 0;
1251 if(ai->length)
1253 ch=0xffff;
1254 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1256 ch = 0;
1257 if(ai_parms[0].length)
1259 ch = GET_WORD(ai_parms[0].info+1);
1260 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1261 if(ch==4) /* explizit CHI in message */
1263 /* check length of B-CH struct */
1264 if((ai_parms[0].info)[3]>=1)
1266 if((ai_parms[0].info)[4]==CHI)
1268 p_chi = &((ai_parms[0].info)[5]);
1270 else
1272 p_chi = &((ai_parms[0].info)[3]);
1274 if(p_chi[0]>35) /* check length of channel ID */
1276 Info = _WRONG_MESSAGE_FORMAT;
1279 else Info = _WRONG_MESSAGE_FORMAT;
1282 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1284 dir = GET_WORD(ai_parms[0].info+3);
1285 ch_mask = 0;
1286 m = 0x3f;
1287 for(i=0; i+5<=ai_parms[0].length; i++)
1289 if(ai_parms[0].info[i+5]!=0)
1291 if((ai_parms[0].info[i+5] | m) != 0xff)
1292 Info = _WRONG_MESSAGE_FORMAT;
1293 else
1295 if (ch_mask == 0)
1296 channel = i;
1297 ch_mask |= 1L << i;
1300 m = 0;
1302 if (ch_mask == 0)
1303 Info = _WRONG_MESSAGE_FORMAT;
1304 if (!Info)
1306 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1308 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1309 for(i=0; i+5<=ai_parms[0].length; i++)
1310 esc_chi[i+3] = ai_parms[0].info[i+5];
1312 else
1313 esc_chi[0] = 2;
1314 esc_chi[2] = (byte)channel;
1315 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1316 add_p(plci,LLI,lli);
1317 add_p(plci,ESC,esc_chi);
1318 plci->State = LOCAL_CONNECT;
1319 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1324 else Info = _WRONG_MESSAGE_FORMAT;
1327 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1328 plci->command = _CONNECT_R;
1329 plci->number = Number;
1330 /* x.31 or D-ch free SAPI in LinkLayer? */
1331 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1332 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1334 /* B-channel used for B3 connections (ch==0), or no B channel */
1335 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1336 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1337 else Info = add_b1(plci,&parms[5],ch,0);
1338 add_s(plci,OAD,&parms[2]);
1339 add_s(plci,OSA,&parms[4]);
1340 add_s(plci,BC,&parms[6]);
1341 add_s(plci,LLC,&parms[7]);
1342 add_s(plci,HLC,&parms[8]);
1343 CIP = GET_WORD(parms[0].info);
1344 if (a->Info_Mask[appl->Id-1] & 0x200)
1346 /* early B3 connect (CIP mask bit 9) no release after a disc */
1347 add_p(plci,LLI,"\x01\x01");
1349 if(GET_WORD(parms[0].info)<29) {
1350 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1351 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1353 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1354 sig_req(plci,ASSIGN,DSIG_ID);
1356 else if(ch==1) {
1358 /* D-Channel used for B3 connections */
1359 plci->Sig.Id = 0xff;
1360 Info = 0;
1363 if(!Info && ch!=2 && !noCh ) {
1364 Info = add_b23(plci,&parms[5]);
1365 if(!Info) {
1366 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1370 if(!Info)
1372 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1374 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1376 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1377 plci->spoofed_msg = CALL_REQ;
1378 plci->internal_command = BLOCK_PLCI;
1379 plci->command = 0;
1380 dbug(1,dprintf("Spoof"));
1381 send_req(plci);
1382 return false;
1384 if(ch==4)add_p(plci,CHI,p_chi);
1385 add_s(plci,CPN,&parms[1]);
1386 add_s(plci,DSA,&parms[3]);
1387 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1388 add_ai(plci,&parms[9]);
1389 if(!dir)sig_req(plci,CALL_REQ,0);
1390 else
1392 plci->command = PERM_LIST_REQ;
1393 plci->appl = appl;
1394 sig_req(plci,LISTEN_REQ,0);
1395 send_req(plci);
1396 return false;
1399 send_req(plci);
1400 return false;
1402 plci->Id = 0;
1405 sendf(appl,
1406 _CONNECT_R|CONFIRM,
1408 Number,
1409 "w",Info);
1410 return 2;
1413 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1414 PLCI *plci, APPL *appl, API_PARSE *parms)
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;
1424 if(!plci) {
1425 dbug(1,dprintf("connect_res(no plci)"));
1426 return 0; /* no plci, no send */
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));
1434 if(ai->length)
1436 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
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)
1442 ch = GET_WORD(ai_parms[0].info+1);
1443 dbug(1,dprintf("BCH-I=0x%x",ch));
1448 if(plci->State==INC_CON_CONNECTED_ALERT)
1450 dbug(1,dprintf("Connected Alert Call_Res"));
1451 if (a->Info_Mask[appl->Id-1] & 0x200)
1453 /* early B3 connect (CIP mask bit 9) no release after a disc */
1454 add_p(plci,LLI,"\x01\x01");
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;
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)
1470 if(c_ind_mask_empty (plci))
1472 if((Reject&0xff00)==0x3400)
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);
1479 else if(Reject==1 || Reject>9)
1481 add_ai(plci, &parms[5]);
1482 sig_req(plci,HANGUP,0);
1484 else
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);
1491 plci->appl = appl;
1493 else
1495 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
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;
1506 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1508 Info = add_b23(plci, &parms[1]);
1509 if (Info)
1511 dbug(1,dprintf("connect_res(error from add_b23)"));
1512 sig_req(plci,HANGUP,0);
1513 return 1;
1515 if(plci->adv_nl)
1517 nl_req_ncci(plci, ASSIGN, 0);
1521 else
1523 plci->tel = 0;
1524 if(ch!=2)
1526 Info = add_b23(plci, &parms[1]);
1527 if (Info)
1529 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1530 sig_req(plci,HANGUP,0);
1531 return 1;
1534 nl_req_ncci(plci, ASSIGN, 0);
1537 if(plci->spoofed_msg==SPOOFING_REQUIRED)
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"));
1545 else
1547 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1548 if (a->Info_Mask[appl->Id-1] & 0x200)
1550 /* early B3 connect (CIP mask bit 9) no release after a disc */
1551 add_p(plci,LLI,"\x01\x01");
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);
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);
1567 return 1;
1570 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1571 PLCI *plci, APPL *appl, API_PARSE *msg)
1573 dbug(1,dprintf("connect_a_res"));
1574 return false;
1577 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1578 PLCI *plci, APPL *appl, API_PARSE *msg)
1580 word Info;
1581 word i;
1583 dbug(1,dprintf("disconnect_req"));
1585 Info = _WRONG_IDENTIFIER;
1587 if(plci)
1589 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1591 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1592 plci->appl = appl;
1593 for(i=0; i<max_appl; i++)
1595 if(test_c_ind_mask_bit (plci, i))
1596 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1598 plci->State = OUTG_DIS_PENDING;
1600 if(plci->Sig.Id && plci->appl)
1602 Info = 0;
1603 if(plci->Sig.Id!=0xff)
1605 if(plci->State!=INC_DIS_PENDING)
1607 add_ai(plci, &msg[0]);
1608 sig_req(plci,HANGUP,0);
1609 plci->State = OUTG_DIS_PENDING;
1610 return 1;
1613 else
1615 if (plci->NL.Id && !plci->nl_remove_id)
1617 mixer_remove (plci);
1618 nl_req_ncci(plci,REMOVE,0);
1619 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1620 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1621 plci->State = INC_DIS_PENDING;
1623 return 1;
1628 if(!appl) return false;
1629 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1630 return false;
1633 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1634 PLCI *plci, APPL *appl, API_PARSE *msg)
1636 dbug(1,dprintf("disconnect_res"));
1637 if(plci)
1639 /* clear ind mask bit, just in case of collsion of */
1640 /* DISCONNECT_IND and CONNECT_RES */
1641 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1642 ncci_free_receive_buffers (plci, 0);
1643 if(plci_remove_check(plci))
1645 return 0;
1647 if(plci->State==INC_DIS_PENDING
1648 || plci->State==SUSPENDING) {
1649 if(c_ind_mask_empty (plci)) {
1650 if(plci->State!=SUSPENDING)plci->State = IDLE;
1651 dbug(1,dprintf("chs=%d",plci->channels));
1652 if(!plci->channels) {
1653 plci_remove(plci);
1658 return 0;
1661 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1662 PLCI *plci, APPL *appl, API_PARSE *parms)
1664 word Info;
1665 byte i;
1667 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1669 Info = _WRONG_IDENTIFIER;
1670 if(a) {
1671 Info = 0;
1672 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1673 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1674 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1675 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1676 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1679 /* check if external controller listen and switch listen on or off*/
1680 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1681 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1682 dummy_plci.State = IDLE;
1683 a->codec_listen[appl->Id-1] = &dummy_plci;
1684 a->TelOAD[0] = (byte)(parms[3].length);
1685 for(i=1;parms[3].length>=i && i<22;i++) {
1686 a->TelOAD[i] = parms[3].info[i];
1688 a->TelOAD[i] = 0;
1689 a->TelOSA[0] = (byte)(parms[4].length);
1690 for(i=1;parms[4].length>=i && i<22;i++) {
1691 a->TelOSA[i] = parms[4].info[i];
1693 a->TelOSA[i] = 0;
1695 else Info = 0x2002; /* wrong controller, codec not supported */
1697 else{ /* clear listen */
1698 a->codec_listen[appl->Id-1] = (PLCI *)0;
1701 sendf(appl,
1702 _LISTEN_R|CONFIRM,
1704 Number,
1705 "w",Info);
1707 if (a) listen_check(a);
1708 return false;
1711 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1712 PLCI *plci, APPL *appl, API_PARSE *msg)
1714 word i;
1715 API_PARSE * ai;
1716 PLCI * rc_plci = NULL;
1717 API_PARSE ai_parms[5];
1718 word Info = 0;
1720 dbug(1,dprintf("info_req"));
1721 for(i=0;i<5;i++) ai_parms[i].length = 0;
1723 ai = &msg[1];
1725 if(ai->length)
1727 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1729 dbug(1,dprintf("AddInfo wrong"));
1730 Info = _WRONG_MESSAGE_FORMAT;
1733 if(!a) Info = _WRONG_STATE;
1735 if(!Info && plci)
1736 { /* no fac, with CPN, or KEY */
1737 rc_plci = plci;
1738 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1740 /* overlap sending option */
1741 dbug(1,dprintf("OvlSnd"));
1742 add_s(plci,CPN,&msg[0]);
1743 add_s(plci,KEY,&ai_parms[1]);
1744 sig_req(plci,INFO_REQ,0);
1745 send_req(plci);
1746 return false;
1749 if(plci->State && ai_parms[2].length)
1751 /* User_Info option */
1752 dbug(1,dprintf("UUI"));
1753 add_s(plci,UUI,&ai_parms[2]);
1754 sig_req(plci,USER_DATA,0);
1756 else if(plci->State && ai_parms[3].length)
1758 /* Facility option */
1759 dbug(1,dprintf("FAC"));
1760 add_s(plci,CPN,&msg[0]);
1761 add_ai(plci, &msg[1]);
1762 sig_req(plci,FACILITY_REQ,0);
1764 else
1766 Info = _WRONG_STATE;
1769 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1771 /* NCR_Facility option -> send UUI and Keypad too */
1772 dbug(1,dprintf("NCR_FAC"));
1773 if((i=get_plci(a)))
1775 rc_plci = &a->plci[i-1];
1776 appl->NullCREnable = true;
1777 rc_plci->internal_command = C_NCR_FAC_REQ;
1778 rc_plci->appl = appl;
1779 add_p(rc_plci,CAI,"\x01\x80");
1780 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1781 sig_req(rc_plci,ASSIGN,DSIG_ID);
1782 send_req(rc_plci);
1784 else
1786 Info = _OUT_OF_PLCI;
1789 if(!Info)
1791 add_s(rc_plci,CPN,&msg[0]);
1792 add_ai(rc_plci, &msg[1]);
1793 sig_req(rc_plci,NCR_FACILITY,0);
1794 send_req(rc_plci);
1795 return false;
1796 /* for application controlled supplementary services */
1800 if (!rc_plci)
1802 Info = _WRONG_MESSAGE_FORMAT;
1805 if(!Info)
1807 send_req(rc_plci);
1809 else
1810 { /* appl is not assigned to a PLCI or error condition */
1811 dbug(1,dprintf("localInfoCon"));
1812 sendf(appl,
1813 _INFO_R|CONFIRM,
1815 Number,
1816 "w",Info);
1818 return false;
1821 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1822 PLCI *plci, APPL *appl, API_PARSE *msg)
1824 dbug(1,dprintf("info_res"));
1825 return false;
1828 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1829 PLCI *plci, APPL *appl, API_PARSE *msg)
1831 word Info;
1832 byte ret;
1834 dbug(1,dprintf("alert_req"));
1836 Info = _WRONG_IDENTIFIER;
1837 ret = false;
1838 if(plci) {
1839 Info = _ALERT_IGNORED;
1840 if(plci->State!=INC_CON_ALERT) {
1841 Info = _WRONG_STATE;
1842 if(plci->State==INC_CON_PENDING) {
1843 Info = 0;
1844 plci->State=INC_CON_ALERT;
1845 add_ai(plci, &msg[0]);
1846 sig_req(plci,CALL_ALERT,0);
1847 ret = 1;
1851 sendf(appl,
1852 _ALERT_R|CONFIRM,
1854 Number,
1855 "w",Info);
1856 return ret;
1859 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1860 PLCI *plci, APPL *appl, API_PARSE *msg)
1862 word Info = 0;
1863 word i = 0;
1865 word selector;
1866 word SSreq;
1867 long relatedPLCIvalue;
1868 DIVA_CAPI_ADAPTER * relatedadapter;
1869 byte * SSparms = "";
1870 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1871 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1872 API_PARSE * parms;
1873 API_PARSE ss_parms[11];
1874 PLCI *rplci;
1875 byte cai[15];
1876 dword d;
1877 API_PARSE dummy;
1879 dbug(1,dprintf("facility_req"));
1880 for(i=0;i<9;i++) ss_parms[i].length = 0;
1882 parms = &msg[1];
1884 if(!a)
1886 dbug(1,dprintf("wrong Ctrl"));
1887 Info = _WRONG_IDENTIFIER;
1890 selector = GET_WORD(msg[0].info);
1892 if(!Info)
1894 switch(selector)
1896 case SELECTOR_HANDSET:
1897 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1898 break;
1900 case SELECTOR_SU_SERV:
1901 if(!msg[1].length)
1903 Info = _WRONG_MESSAGE_FORMAT;
1904 break;
1906 SSreq = GET_WORD(&(msg[1].info[1]));
1907 PUT_WORD(&RCparms[1],SSreq);
1908 SSparms = RCparms;
1909 switch(SSreq)
1911 case S_GET_SUPPORTED_SERVICES:
1912 if((i=get_plci(a)))
1914 rplci = &a->plci[i-1];
1915 rplci->appl = appl;
1916 add_p(rplci,CAI,"\x01\x80");
1917 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1918 sig_req(rplci,ASSIGN,DSIG_ID);
1919 send_req(rplci);
1921 else
1923 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1924 SSparms = (byte *)SSstruct;
1925 break;
1927 rplci->internal_command = GETSERV_REQ_PEND;
1928 rplci->number = Number;
1929 rplci->appl = appl;
1930 sig_req(rplci,S_SUPPORTED,0);
1931 send_req(rplci);
1932 return false;
1933 break;
1935 case S_LISTEN:
1936 if(parms->length==7)
1938 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1940 dbug(1,dprintf("format wrong"));
1941 Info = _WRONG_MESSAGE_FORMAT;
1942 break;
1945 else
1947 Info = _WRONG_MESSAGE_FORMAT;
1948 break;
1950 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1951 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1953 if((i=get_plci(a)))
1955 rplci = &a->plci[i-1];
1956 rplci->appl = appl;
1957 add_p(rplci,CAI,"\x01\x80");
1958 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1959 sig_req(rplci,ASSIGN,DSIG_ID);
1960 send_req(rplci);
1962 else
1964 break;
1966 rplci->internal_command = GET_MWI_STATE;
1967 rplci->number = Number;
1968 sig_req(rplci,MWI_POLL,0);
1969 send_req(rplci);
1971 break;
1973 case S_HOLD:
1974 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1975 if(plci && plci->State && plci->SuppState==IDLE)
1977 plci->SuppState = HOLD_REQUEST;
1978 plci->command = C_HOLD_REQ;
1979 add_s(plci,CAI,&ss_parms[1]);
1980 sig_req(plci,CALL_HOLD,0);
1981 send_req(plci);
1982 return false;
1984 else Info = 0x3010; /* wrong state */
1985 break;
1986 case S_RETRIEVE:
1987 if(plci && plci->State && plci->SuppState==CALL_HELD)
1989 if(Id & EXT_CONTROLLER)
1991 if(AdvCodecSupport(a, plci, appl, 0))
1993 Info = 0x3010; /* wrong state */
1994 break;
1997 else plci->tel = 0;
1999 plci->SuppState = RETRIEVE_REQUEST;
2000 plci->command = C_RETRIEVE_REQ;
2001 if(plci->spoofed_msg==SPOOFING_REQUIRED)
2003 plci->spoofed_msg = CALL_RETRIEVE;
2004 plci->internal_command = BLOCK_PLCI;
2005 plci->command = 0;
2006 dbug(1,dprintf("Spoof"));
2007 return false;
2009 else
2011 sig_req(plci,CALL_RETRIEVE,0);
2012 send_req(plci);
2013 return false;
2016 else Info = 0x3010; /* wrong state */
2017 break;
2018 case S_SUSPEND:
2019 if(parms->length)
2021 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2023 dbug(1,dprintf("format wrong"));
2024 Info = _WRONG_MESSAGE_FORMAT;
2025 break;
2028 if(plci && plci->State)
2030 add_s(plci,CAI,&ss_parms[2]);
2031 plci->command = SUSPEND_REQ;
2032 sig_req(plci,SUSPEND,0);
2033 plci->State = SUSPENDING;
2034 send_req(plci);
2036 else Info = 0x3010; /* wrong state */
2037 break;
2039 case S_RESUME:
2040 if(!(i=get_plci(a)) )
2042 Info = _OUT_OF_PLCI;
2043 break;
2045 rplci = &a->plci[i-1];
2046 rplci->appl = appl;
2047 rplci->number = Number;
2048 rplci->tel = 0;
2049 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2050 /* check 'external controller' bit for codec support */
2051 if(Id & EXT_CONTROLLER)
2053 if(AdvCodecSupport(a, rplci, appl, 0) )
2055 rplci->Id = 0;
2056 Info = 0x300A;
2057 break;
2060 if(parms->length)
2062 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2064 dbug(1,dprintf("format wrong"));
2065 rplci->Id = 0;
2066 Info = _WRONG_MESSAGE_FORMAT;
2067 break;
2070 dummy.length = 0;
2071 dummy.info = "\x00";
2072 add_b1(rplci, &dummy, 0, 0);
2073 if (a->Info_Mask[appl->Id-1] & 0x200)
2075 /* early B3 connect (CIP mask bit 9) no release after a disc */
2076 add_p(rplci,LLI,"\x01\x01");
2078 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2079 sig_req(rplci,ASSIGN,DSIG_ID);
2080 send_req(rplci);
2081 add_s(rplci,CAI,&ss_parms[2]);
2082 rplci->command = RESUME_REQ;
2083 sig_req(rplci,RESUME,0);
2084 rplci->State = RESUMING;
2085 send_req(rplci);
2086 break;
2088 case S_CONF_BEGIN: /* Request */
2089 case S_CONF_DROP:
2090 case S_CONF_ISOLATE:
2091 case S_CONF_REATTACH:
2092 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2094 dbug(1,dprintf("format wrong"));
2095 Info = _WRONG_MESSAGE_FORMAT;
2096 break;
2098 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2100 d = GET_DWORD(ss_parms[2].info);
2101 if(d>=0x80)
2103 dbug(1,dprintf("format wrong"));
2104 Info = _WRONG_MESSAGE_FORMAT;
2105 break;
2107 plci->ptyState = (byte)SSreq;
2108 plci->command = 0;
2109 cai[0] = 2;
2110 switch(SSreq)
2112 case S_CONF_BEGIN:
2113 cai[1] = CONF_BEGIN;
2114 plci->internal_command = CONF_BEGIN_REQ_PEND;
2115 break;
2116 case S_CONF_DROP:
2117 cai[1] = CONF_DROP;
2118 plci->internal_command = CONF_DROP_REQ_PEND;
2119 break;
2120 case S_CONF_ISOLATE:
2121 cai[1] = CONF_ISOLATE;
2122 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2123 break;
2124 case S_CONF_REATTACH:
2125 cai[1] = CONF_REATTACH;
2126 plci->internal_command = CONF_REATTACH_REQ_PEND;
2127 break;
2129 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2130 add_p(plci,CAI,cai);
2131 sig_req(plci,S_SERVICE,0);
2132 send_req(plci);
2133 return false;
2135 else Info = 0x3010; /* wrong state */
2136 break;
2138 case S_ECT:
2139 case S_3PTY_BEGIN:
2140 case S_3PTY_END:
2141 case S_CONF_ADD:
2142 if(parms->length==7)
2144 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2146 dbug(1,dprintf("format wrong"));
2147 Info = _WRONG_MESSAGE_FORMAT;
2148 break;
2151 else if(parms->length==8)
2153 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2155 dbug(1,dprintf("format wrong"));
2156 Info = _WRONG_MESSAGE_FORMAT;
2157 break;
2160 else
2162 Info = _WRONG_MESSAGE_FORMAT;
2163 break;
2165 if(!msg[1].length)
2167 Info = _WRONG_MESSAGE_FORMAT;
2168 break;
2170 if (!plci)
2172 Info = _WRONG_IDENTIFIER;
2173 break;
2175 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2176 relatedPLCIvalue &= 0x0000FFFF;
2177 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2178 /* controller starts with 0 up to (max_adapter - 1) */
2179 if (((relatedPLCIvalue & 0x7f) == 0)
2180 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2181 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2183 if(SSreq==S_3PTY_END)
2185 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2186 rplci = plci;
2188 else
2190 Info = 0x3010; /* wrong state */
2191 break;
2194 else
2196 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2197 relatedPLCIvalue >>=8;
2198 /* find PLCI PTR*/
2199 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2201 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2203 rplci = &relatedadapter->plci[i];
2206 if(!rplci || !relatedPLCIvalue)
2208 if(SSreq==S_3PTY_END)
2210 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2211 rplci = plci;
2213 else
2215 Info = 0x3010; /* wrong state */
2216 break;
2221 dbug(1,dprintf("rplci:%x",rplci));
2222 dbug(1,dprintf("plci:%x",plci));
2223 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2224 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2225 dbug(1,dprintf("SSreq:%x",SSreq));
2226 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2227 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2228 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2230 /* send PTY/ECT req, cannot check all states because of US stuff */
2231 if( !rplci->internal_command && rplci->appl )
2233 plci->command = 0;
2234 rplci->relatedPTYPLCI = plci;
2235 plci->relatedPTYPLCI = rplci;
2236 rplci->ptyState = (byte)SSreq;
2237 if(SSreq==S_ECT)
2239 rplci->internal_command = ECT_REQ_PEND;
2240 cai[1] = ECT_EXECUTE;
2242 rplci->vswitchstate=0;
2243 rplci->vsprot=0;
2244 rplci->vsprotdialect=0;
2245 plci->vswitchstate=0;
2246 plci->vsprot=0;
2247 plci->vsprotdialect=0;
2250 else if(SSreq==S_CONF_ADD)
2252 rplci->internal_command = CONF_ADD_REQ_PEND;
2253 cai[1] = CONF_ADD;
2255 else
2257 rplci->internal_command = PTY_REQ_PEND;
2258 cai[1] = (byte)(SSreq-3);
2260 rplci->number = Number;
2261 if(plci!=rplci) /* explicit invocation */
2263 cai[0] = 2;
2264 cai[2] = plci->Sig.Id;
2265 dbug(1,dprintf("explicit invocation"));
2267 else
2269 dbug(1,dprintf("implicit invocation"));
2270 cai[0] = 1;
2272 add_p(rplci,CAI,cai);
2273 sig_req(rplci,S_SERVICE,0);
2274 send_req(rplci);
2275 return false;
2277 else
2279 dbug(0,dprintf("Wrong line"));
2280 Info = 0x3010; /* wrong state */
2281 break;
2283 break;
2285 case S_CALL_DEFLECTION:
2286 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2288 dbug(1,dprintf("format wrong"));
2289 Info = _WRONG_MESSAGE_FORMAT;
2290 break;
2292 if (!plci)
2294 Info = _WRONG_IDENTIFIER;
2295 break;
2297 /* reuse unused screening indicator */
2298 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2299 plci->command = 0;
2300 plci->internal_command = CD_REQ_PEND;
2301 appl->CDEnable = true;
2302 cai[0] = 1;
2303 cai[1] = CALL_DEFLECTION;
2304 add_p(plci,CAI,cai);
2305 add_p(plci,CPN,ss_parms[3].info);
2306 sig_req(plci,S_SERVICE,0);
2307 send_req(plci);
2308 return false;
2309 break;
2311 case S_CALL_FORWARDING_START:
2312 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2314 dbug(1,dprintf("format wrong"));
2315 Info = _WRONG_MESSAGE_FORMAT;
2316 break;
2319 if((i=get_plci(a)))
2321 rplci = &a->plci[i-1];
2322 rplci->appl = appl;
2323 add_p(rplci,CAI,"\x01\x80");
2324 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2325 sig_req(rplci,ASSIGN,DSIG_ID);
2326 send_req(rplci);
2328 else
2330 Info = _OUT_OF_PLCI;
2331 break;
2334 /* reuse unused screening indicator */
2335 rplci->internal_command = CF_START_PEND;
2336 rplci->appl = appl;
2337 rplci->number = Number;
2338 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2339 cai[0] = 2;
2340 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2341 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2342 add_p(rplci,CAI,cai);
2343 add_p(rplci,OAD,ss_parms[5].info);
2344 add_p(rplci,CPN,ss_parms[6].info);
2345 sig_req(rplci,S_SERVICE,0);
2346 send_req(rplci);
2347 return false;
2348 break;
2350 case S_INTERROGATE_DIVERSION:
2351 case S_INTERROGATE_NUMBERS:
2352 case S_CALL_FORWARDING_STOP:
2353 case S_CCBS_REQUEST:
2354 case S_CCBS_DEACTIVATE:
2355 case S_CCBS_INTERROGATE:
2356 switch(SSreq)
2358 case S_INTERROGATE_NUMBERS:
2359 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2361 dbug(0,dprintf("format wrong"));
2362 Info = _WRONG_MESSAGE_FORMAT;
2364 break;
2365 case S_CCBS_REQUEST:
2366 case S_CCBS_DEACTIVATE:
2367 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2369 dbug(0,dprintf("format wrong"));
2370 Info = _WRONG_MESSAGE_FORMAT;
2372 break;
2373 case S_CCBS_INTERROGATE:
2374 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2376 dbug(0,dprintf("format wrong"));
2377 Info = _WRONG_MESSAGE_FORMAT;
2379 break;
2380 default:
2381 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2383 dbug(0,dprintf("format wrong"));
2384 Info = _WRONG_MESSAGE_FORMAT;
2385 break;
2387 break;
2390 if(Info) break;
2391 if((i=get_plci(a)))
2393 rplci = &a->plci[i-1];
2394 switch(SSreq)
2396 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2397 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2398 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2399 break;
2400 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2401 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2402 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2403 break;
2404 case S_CALL_FORWARDING_STOP:
2405 rplci->internal_command = CF_STOP_PEND;
2406 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2407 break;
2408 case S_CCBS_REQUEST:
2409 cai[1] = CCBS_REQUEST;
2410 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2411 break;
2412 case S_CCBS_DEACTIVATE:
2413 cai[1] = CCBS_DEACTIVATE;
2414 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2415 break;
2416 case S_CCBS_INTERROGATE:
2417 cai[1] = CCBS_INTERROGATE;
2418 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2419 break;
2420 default:
2421 cai[1] = 0;
2422 break;
2424 rplci->appl = appl;
2425 rplci->number = Number;
2426 add_p(rplci,CAI,"\x01\x80");
2427 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2428 sig_req(rplci,ASSIGN,DSIG_ID);
2429 send_req(rplci);
2431 else
2433 Info = _OUT_OF_PLCI;
2434 break;
2437 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2438 switch(SSreq)
2440 case S_INTERROGATE_NUMBERS:
2441 cai[0] = 1;
2442 add_p(rplci,CAI,cai);
2443 break;
2444 case S_CCBS_REQUEST:
2445 case S_CCBS_DEACTIVATE:
2446 cai[0] = 3;
2447 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2448 add_p(rplci,CAI,cai);
2449 break;
2450 case S_CCBS_INTERROGATE:
2451 cai[0] = 3;
2452 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2453 add_p(rplci,CAI,cai);
2454 add_p(rplci,OAD,ss_parms[4].info);
2455 break;
2456 default:
2457 cai[0] = 2;
2458 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2459 add_p(rplci,CAI,cai);
2460 add_p(rplci,OAD,ss_parms[5].info);
2461 break;
2464 sig_req(rplci,S_SERVICE,0);
2465 send_req(rplci);
2466 return false;
2467 break;
2469 case S_MWI_ACTIVATE:
2470 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2472 dbug(1,dprintf("format wrong"));
2473 Info = _WRONG_MESSAGE_FORMAT;
2474 break;
2476 if(!plci)
2478 if((i=get_plci(a)))
2480 rplci = &a->plci[i-1];
2481 rplci->appl = appl;
2482 rplci->cr_enquiry=true;
2483 add_p(rplci,CAI,"\x01\x80");
2484 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2485 sig_req(rplci,ASSIGN,DSIG_ID);
2486 send_req(rplci);
2488 else
2490 Info = _OUT_OF_PLCI;
2491 break;
2494 else
2496 rplci = plci;
2497 rplci->cr_enquiry=false;
2500 rplci->command = 0;
2501 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2502 rplci->appl = appl;
2503 rplci->number = Number;
2505 cai[0] = 13;
2506 cai[1] = ACTIVATION_MWI; /* Function */
2507 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2508 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2509 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2510 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2511 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2512 add_p(rplci,CAI,cai);
2513 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2514 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2515 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2516 add_p(rplci,UID,ss_parms[10].info); /* Time */
2517 sig_req(rplci,S_SERVICE,0);
2518 send_req(rplci);
2519 return false;
2521 case S_MWI_DEACTIVATE:
2522 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2524 dbug(1,dprintf("format wrong"));
2525 Info = _WRONG_MESSAGE_FORMAT;
2526 break;
2528 if(!plci)
2530 if((i=get_plci(a)))
2532 rplci = &a->plci[i-1];
2533 rplci->appl = appl;
2534 rplci->cr_enquiry=true;
2535 add_p(rplci,CAI,"\x01\x80");
2536 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2537 sig_req(rplci,ASSIGN,DSIG_ID);
2538 send_req(rplci);
2540 else
2542 Info = _OUT_OF_PLCI;
2543 break;
2546 else
2548 rplci = plci;
2549 rplci->cr_enquiry=false;
2552 rplci->command = 0;
2553 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2554 rplci->appl = appl;
2555 rplci->number = Number;
2557 cai[0] = 5;
2558 cai[1] = DEACTIVATION_MWI; /* Function */
2559 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2560 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2561 add_p(rplci,CAI,cai);
2562 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2563 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2564 sig_req(rplci,S_SERVICE,0);
2565 send_req(rplci);
2566 return false;
2568 default:
2569 Info = 0x300E; /* not supported */
2570 break;
2572 break; /* case SELECTOR_SU_SERV: end */
2575 case SELECTOR_DTMF:
2576 return (dtmf_request (Id, Number, a, plci, appl, msg));
2580 case SELECTOR_LINE_INTERCONNECT:
2581 return (mixer_request (Id, Number, a, plci, appl, msg));
2585 case PRIV_SELECTOR_ECHO_CANCELLER:
2586 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2587 return (ec_request (Id, Number, a, plci, appl, msg));
2589 case SELECTOR_ECHO_CANCELLER:
2590 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2591 return (ec_request (Id, Number, a, plci, appl, msg));
2594 case SELECTOR_V42BIS:
2595 default:
2596 Info = _FACILITY_NOT_SUPPORTED;
2597 break;
2598 } /* end of switch(selector) */
2601 dbug(1,dprintf("SendFacRc"));
2602 sendf(appl,
2603 _FACILITY_R|CONFIRM,
2605 Number,
2606 "wws",Info,selector,SSparms);
2607 return false;
2610 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2611 PLCI *plci, APPL *appl, API_PARSE *msg)
2613 dbug(1,dprintf("facility_res"));
2614 return false;
2617 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2618 PLCI *plci, APPL *appl, API_PARSE *parms)
2620 word Info = 0;
2621 byte req;
2622 byte len;
2623 word w;
2624 word fax_control_bits, fax_feature_bits, fax_info_change;
2625 API_PARSE * ncpi;
2626 byte pvc[2];
2628 API_PARSE fax_parms[9];
2629 word i;
2632 dbug(1,dprintf("connect_b3_req"));
2633 if(plci)
2635 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2636 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2638 Info = _WRONG_STATE;
2640 else
2642 /* local reply if assign unsuccessfull
2643 or B3 protocol allows only one layer 3 connection
2644 and already connected
2645 or B2 protocol not any LAPD
2646 and connect_b3_req contradicts originate/answer direction */
2647 if (!plci->NL.Id
2648 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2649 && ((plci->channels != 0)
2650 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2651 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2653 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2654 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2655 Info = _WRONG_STATE;
2656 sendf(appl,
2657 _CONNECT_B3_R|CONFIRM,
2659 Number,
2660 "w",Info);
2661 return false;
2663 plci->requested_options_conn = 0;
2665 req = N_CONNECT;
2666 ncpi = &parms[0];
2667 if(plci->B3_prot==2 || plci->B3_prot==3)
2669 if(ncpi->length>2)
2671 /* check for PVC */
2672 if(ncpi->info[2] || ncpi->info[3])
2674 pvc[0] = ncpi->info[3];
2675 pvc[1] = ncpi->info[2];
2676 add_d(plci,2,pvc);
2677 req = N_RESET;
2679 else
2681 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2682 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2686 else if(plci->B3_prot==5)
2688 if (plci->NL.Id && !plci->nl_remove_id)
2690 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2691 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2692 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2693 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2695 len = offsetof(T30_INFO, universal_6);
2696 fax_info_change = false;
2697 if (ncpi->length >= 4)
2699 w = GET_WORD(&ncpi->info[3]);
2700 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2702 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2703 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2704 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2705 fax_info_change = true;
2707 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2708 if (w & 0x0002) /* Fax-polling request */
2709 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2710 if ((w & 0x0004) /* Request to send / poll another document */
2711 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2713 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2715 if (ncpi->length >= 6)
2717 w = GET_WORD(&ncpi->info[5]);
2718 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2720 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2721 fax_info_change = true;
2724 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2725 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2727 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2729 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2730 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2732 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2734 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2735 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2736 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2737 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2739 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2740 Info = _WRONG_MESSAGE_FORMAT;
2741 else
2743 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2744 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2746 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2747 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2748 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2750 w = fax_parms[4].length;
2751 if (w > 20)
2752 w = 20;
2753 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2754 for (i = 0; i < w; i++)
2755 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2756 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2757 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2758 w = fax_parms[5].length;
2759 if (w > 20)
2760 w = 20;
2761 plci->fax_connect_info_buffer[len++] = (byte) w;
2762 for (i = 0; i < w; i++)
2763 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2764 w = fax_parms[6].length;
2765 if (w > 20)
2766 w = 20;
2767 plci->fax_connect_info_buffer[len++] = (byte) w;
2768 for (i = 0; i < w; i++)
2769 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2770 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2771 & (1L << PRIVATE_FAX_NONSTANDARD))
2773 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2775 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2776 plci->fax_connect_info_buffer[len++] = 0;
2778 else
2780 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2781 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2782 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2783 for (i = 0; i < fax_parms[7].length; i++)
2784 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2789 else
2791 len = offsetof(T30_INFO, universal_6);
2793 fax_info_change = true;
2796 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2798 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2799 fax_info_change = true;
2802 if (Info == GOOD)
2804 plci->fax_connect_info_length = len;
2805 if (fax_info_change)
2807 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2809 start_internal_command (Id, plci, fax_connect_info_command);
2810 return false;
2812 else
2814 start_internal_command (Id, plci, fax_adjust_b23_command);
2815 return false;
2820 else Info = _WRONG_STATE;
2822 else Info = _WRONG_STATE;
2825 else if (plci->B3_prot == B3_RTP)
2827 plci->internal_req_buffer[0] = ncpi->length + 1;
2828 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2829 for (w = 0; w < ncpi->length; w++)
2830 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2831 start_internal_command (Id, plci, rtp_connect_b3_req_command);
2832 return false;
2835 if(!Info)
2837 nl_req_ncci(plci,req,0);
2838 return 1;
2842 else Info = _WRONG_IDENTIFIER;
2844 sendf(appl,
2845 _CONNECT_B3_R|CONFIRM,
2847 Number,
2848 "w",Info);
2849 return false;
2852 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2853 PLCI *plci, APPL *appl, API_PARSE *parms)
2855 word ncci;
2856 API_PARSE * ncpi;
2857 byte req;
2859 word w;
2862 API_PARSE fax_parms[9];
2863 word i;
2864 byte len;
2867 dbug(1,dprintf("connect_b3_res"));
2869 ncci = (word)(Id>>16);
2870 if(plci && ncci) {
2871 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2872 if (GET_WORD (&parms[0].info[0]) != 0)
2874 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2875 channel_request_xon (plci, a->ncci_ch[ncci]);
2876 channel_xmit_xon (plci);
2877 cleanup_ncci_data (plci, ncci);
2878 nl_req_ncci(plci,N_DISC,(byte)ncci);
2879 return 1;
2881 a->ncci_state[ncci] = INC_ACT_PENDING;
2883 req = N_CONNECT_ACK;
2884 ncpi = &parms[1];
2885 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2888 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2889 & (1L << PRIVATE_FAX_NONSTANDARD))
2891 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2892 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2893 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2895 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2896 if (plci->fax_connect_info_length < len)
2898 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2899 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2901 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2903 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2905 else
2907 if (plci->fax_connect_info_length <= len)
2908 plci->fax_connect_info_buffer[len] = 0;
2909 len += 1 + plci->fax_connect_info_buffer[len];
2910 if (plci->fax_connect_info_length <= len)
2911 plci->fax_connect_info_buffer[len] = 0;
2912 len += 1 + plci->fax_connect_info_buffer[len];
2913 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2914 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2915 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2916 for (i = 0; i < fax_parms[7].length; i++)
2917 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2919 plci->fax_connect_info_length = len;
2920 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2921 start_internal_command (Id, plci, fax_connect_ack_command);
2922 return false;
2926 nl_req_ncci(plci,req,(byte)ncci);
2927 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2928 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2930 if (plci->B3_prot == 4)
2931 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2932 else
2933 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2934 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2938 else if (plci->B3_prot == B3_RTP)
2940 plci->internal_req_buffer[0] = ncpi->length + 1;
2941 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2942 for (w = 0; w < ncpi->length; w++)
2943 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2944 start_internal_command (Id, plci, rtp_connect_b3_res_command);
2945 return false;
2948 else
2950 if(ncpi->length>2) {
2951 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2952 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2954 nl_req_ncci(plci,req,(byte)ncci);
2955 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2956 if (plci->adjust_b_restore)
2958 plci->adjust_b_restore = false;
2959 start_internal_command (Id, plci, adjust_b_restore);
2962 return 1;
2965 return false;
2968 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2969 PLCI *plci, APPL *appl, API_PARSE *parms)
2971 word ncci;
2973 ncci = (word)(Id>>16);
2974 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2976 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2977 && (plci->State != OUTG_DIS_PENDING))
2979 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2980 a->ncci_state[ncci] = CONNECTED;
2981 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2982 channel_request_xon (plci, a->ncci_ch[ncci]);
2983 channel_xmit_xon (plci);
2986 return false;
2989 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2990 PLCI *plci, APPL *appl, API_PARSE *parms)
2992 word Info;
2993 word ncci;
2994 API_PARSE * ncpi;
2996 dbug(1,dprintf("disconnect_b3_req"));
2998 Info = _WRONG_IDENTIFIER;
2999 ncci = (word)(Id>>16);
3000 if (plci && ncci)
3002 Info = _WRONG_STATE;
3003 if ((a->ncci_state[ncci] == CONNECTED)
3004 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3005 || (a->ncci_state[ncci] == INC_CON_PENDING)
3006 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3008 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3009 channel_request_xon (plci, a->ncci_ch[ncci]);
3010 channel_xmit_xon (plci);
3012 if (a->ncci[ncci].data_pending
3013 && ((plci->B3_prot == B3_TRANSPARENT)
3014 || (plci->B3_prot == B3_T30)
3015 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3017 plci->send_disc = (byte)ncci;
3018 plci->command = 0;
3019 return false;
3021 else
3023 cleanup_ncci_data (plci, ncci);
3025 if(plci->B3_prot==2 || plci->B3_prot==3)
3027 ncpi = &parms[0];
3028 if(ncpi->length>3)
3030 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3033 nl_req_ncci(plci,N_DISC,(byte)ncci);
3035 return 1;
3038 sendf(appl,
3039 _DISCONNECT_B3_R|CONFIRM,
3041 Number,
3042 "w",Info);
3043 return false;
3046 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3047 PLCI *plci, APPL *appl, API_PARSE *parms)
3049 word ncci;
3050 word i;
3052 ncci = (word)(Id>>16);
3053 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3054 if(plci && ncci) {
3055 plci->requested_options_conn = 0;
3056 plci->fax_connect_info_length = 0;
3057 plci->ncpi_state = 0x00;
3058 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3059 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3061 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3063 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3064 if(i<MAX_CHANNELS_PER_PLCI) {
3065 if(plci->channels)plci->channels--;
3066 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3067 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3069 ncci_free_receive_buffers (plci, ncci);
3071 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3072 if(plci->State == SUSPENDING){
3073 sendf(plci->appl,
3074 _FACILITY_I,
3075 Id & 0xffffL,
3077 "ws", (word)3, "\x03\x04\x00\x00");
3078 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3080 plci_remove(plci);
3081 plci->State=IDLE;
3084 else
3086 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3087 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3088 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3090 ncci_free_receive_buffers (plci, ncci);
3092 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3094 plci->adapter->ncci_state[ncci] = IDLE;
3095 start_internal_command (Id, plci, fax_disconnect_command);
3096 return 1;
3100 return false;
3103 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3104 PLCI *plci, APPL *appl, API_PARSE *parms)
3106 NCCI *ncci_ptr;
3107 DATA_B3_DESC *data;
3108 word Info;
3109 word ncci;
3110 word i;
3112 dbug(1,dprintf("data_b3_req"));
3114 Info = _WRONG_IDENTIFIER;
3115 ncci = (word)(Id>>16);
3116 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3118 if (plci && ncci)
3120 Info = _WRONG_STATE;
3121 if ((a->ncci_state[ncci] == CONNECTED)
3122 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3124 /* queue data */
3125 ncci_ptr = &(a->ncci[ncci]);
3126 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3127 if (i >= MAX_DATA_B3)
3128 i -= MAX_DATA_B3;
3129 data = &(ncci_ptr->DBuffer[i]);
3130 data->Number = Number;
3131 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3132 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3135 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3138 else
3139 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3140 data->Length = GET_WORD(parms[1].info);
3141 data->Handle = GET_WORD(parms[2].info);
3142 data->Flags = GET_WORD(parms[3].info);
3143 (ncci_ptr->data_pending)++;
3145 /* check for delivery confirmation */
3146 if (data->Flags & 0x0004)
3148 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3149 if (i >= MAX_DATA_ACK)
3150 i -= MAX_DATA_ACK;
3151 ncci_ptr->DataAck[i].Number = data->Number;
3152 ncci_ptr->DataAck[i].Handle = data->Handle;
3153 (ncci_ptr->data_ack_pending)++;
3156 send_data(plci);
3157 return false;
3160 if (appl)
3162 if (plci)
3164 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3165 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3168 TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3172 sendf(appl,
3173 _DATA_B3_R|CONFIRM,
3175 Number,
3176 "ww",GET_WORD(parms[2].info),Info);
3178 return false;
3181 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3182 PLCI *plci, APPL *appl, API_PARSE *parms)
3184 word n;
3185 word ncci;
3186 word NCCIcode;
3188 dbug(1,dprintf("data_b3_res"));
3190 ncci = (word)(Id>>16);
3191 if(plci && ncci) {
3192 n = GET_WORD(parms[0].info);
3193 dbug(1,dprintf("free(%d)",n));
3194 NCCIcode = ncci | (((word) a->Id) << 8);
3195 if(n<appl->MaxBuffer &&
3196 appl->DataNCCI[n]==NCCIcode &&
3197 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3198 dbug(1,dprintf("found"));
3199 appl->DataNCCI[n] = 0;
3201 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3202 channel_request_xon (plci, a->ncci_ch[ncci]);
3204 channel_xmit_xon (plci);
3206 if(appl->DataFlags[n] &4) {
3207 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3208 return 1;
3212 return false;
3215 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3216 PLCI *plci, APPL *appl, API_PARSE *parms)
3218 word Info;
3219 word ncci;
3221 dbug(1,dprintf("reset_b3_req"));
3223 Info = _WRONG_IDENTIFIER;
3224 ncci = (word)(Id>>16);
3225 if(plci && ncci)
3227 Info = _WRONG_STATE;
3228 switch (plci->B3_prot)
3230 case B3_ISO8208:
3231 case B3_X25_DCE:
3232 if(a->ncci_state[ncci]==CONNECTED)
3234 nl_req_ncci(plci,N_RESET,(byte)ncci);
3235 send_req(plci);
3236 Info = GOOD;
3238 break;
3239 case B3_TRANSPARENT:
3240 if(a->ncci_state[ncci]==CONNECTED)
3242 start_internal_command (Id, plci, reset_b3_command);
3243 Info = GOOD;
3245 break;
3248 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3249 sendf(appl,
3250 _RESET_B3_R|CONFIRM,
3252 Number,
3253 "w",Info);
3254 return false;
3257 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3258 PLCI *plci, APPL *appl, API_PARSE *parms)
3260 word ncci;
3262 dbug(1,dprintf("reset_b3_res"));
3264 ncci = (word)(Id>>16);
3265 if(plci && ncci) {
3266 switch (plci->B3_prot)
3268 case B3_ISO8208:
3269 case B3_X25_DCE:
3270 if(a->ncci_state[ncci]==INC_RES_PENDING)
3272 a->ncci_state[ncci] = CONNECTED;
3273 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3274 return true;
3276 break;
3279 return false;
3282 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3283 PLCI *plci, APPL *appl, API_PARSE *parms)
3285 word ncci;
3286 API_PARSE * ncpi;
3287 byte req;
3289 dbug(1,dprintf("connect_b3_t90_a_res"));
3291 ncci = (word)(Id>>16);
3292 if(plci && ncci) {
3293 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3294 a->ncci_state[ncci] = CONNECTED;
3296 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3297 a->ncci_state[ncci] = CONNECTED;
3299 req = N_CONNECT_ACK;
3301 /* parms[0]==0 for CAPI original message definition! */
3302 if(parms[0].info) {
3303 ncpi = &parms[1];
3304 if(ncpi->length>2) {
3305 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3306 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3309 nl_req_ncci(plci,req,(byte)ncci);
3310 return 1;
3313 return false;
3317 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3318 PLCI *plci, APPL *appl, API_PARSE *msg)
3320 word Info=0;
3321 word i;
3322 byte tel;
3323 API_PARSE bp_parms[7];
3325 if(!plci || !msg)
3327 Info = _WRONG_IDENTIFIER;
3329 else
3331 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3332 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3333 dbug(1,dprintf("PlciState=0x%x",plci->State));
3334 for(i=0;i<7;i++) bp_parms[i].length = 0;
3336 /* check if no channel is open, no B3 connected only */
3337 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3338 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3340 Info = _WRONG_STATE;
3342 /* check message format and fill bp_parms pointer */
3343 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3345 Info = _WRONG_MESSAGE_FORMAT;
3347 else
3349 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3350 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3351 if(Id & EXT_CONTROLLER)
3353 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3354 return 0;
3356 plci->State=INC_CON_CONNECTED_ALERT;
3357 plci->appl = appl;
3358 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3359 dump_c_ind_mask (plci);
3360 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3361 { /* its quasi a connect */
3362 if(test_c_ind_mask_bit (plci, i))
3363 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3367 api_save_msg(msg, "s", &plci->saved_msg);
3368 tel = plci->tel;
3369 if(Id & EXT_CONTROLLER)
3371 if(tel) /* external controller in use by this PLCI */
3373 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3375 dbug(1,dprintf("Ext_Ctrl in use 1"));
3376 Info = _WRONG_STATE;
3379 else /* external controller NOT in use by this PLCI ? */
3381 if(a->AdvSignalPLCI)
3383 dbug(1,dprintf("Ext_Ctrl in use 2"));
3384 Info = _WRONG_STATE;
3386 else /* activate the codec */
3388 dbug(1,dprintf("Ext_Ctrl start"));
3389 if(AdvCodecSupport(a, plci, appl, 0) )
3391 dbug(1,dprintf("Error in codec procedures"));
3392 Info = _WRONG_STATE;
3394 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3396 plci->spoofed_msg = AWAITING_SELECT_B;
3397 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3398 plci->command = 0;
3399 dbug(1,dprintf("continue if codec loaded"));
3400 return false;
3405 else /* external controller bit is OFF */
3407 if(tel) /* external controller in use, need to switch off */
3409 if(a->AdvSignalAppl==appl)
3411 CodecIdCheck(a, plci);
3412 plci->tel = 0;
3413 plci->adv_nl = 0;
3414 dbug(1,dprintf("Ext_Ctrl disable"));
3416 else
3418 dbug(1,dprintf("Ext_Ctrl not requested"));
3422 if (!Info)
3424 if (plci->call_dir & CALL_DIR_OUT)
3425 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3426 else if (plci->call_dir & CALL_DIR_IN)
3427 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3428 start_internal_command (Id, plci, select_b_command);
3429 return false;
3433 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3434 return false;
3437 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3438 PLCI *plci, APPL *appl, API_PARSE *parms)
3440 word command;
3441 word i;
3442 word ncci;
3443 API_PARSE * m;
3444 API_PARSE m_parms[5];
3445 word codec;
3446 byte req;
3447 byte ch;
3448 byte dir;
3449 static byte chi[2] = {0x01,0x00};
3450 static byte lli[2] = {0x01,0x00};
3451 static byte codec_cai[2] = {0x01,0x01};
3452 static byte null_msg = {0};
3453 static API_PARSE null_parms = { 0, &null_msg };
3454 PLCI * v_plci;
3455 word Info=0;
3457 dbug(1,dprintf("manufacturer_req"));
3458 for(i=0;i<5;i++) m_parms[i].length = 0;
3460 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3461 Info = _WRONG_MESSAGE_FORMAT;
3463 command = GET_WORD(parms[1].info);
3464 m = &parms[2];
3465 if (!Info)
3467 switch(command) {
3468 case _DI_ASSIGN_PLCI:
3469 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3470 Info = _WRONG_MESSAGE_FORMAT;
3471 break;
3473 codec = GET_WORD(m_parms[0].info);
3474 ch = m_parms[1].info[0];
3475 dir = m_parms[2].info[0];
3476 if((i=get_plci(a))) {
3477 plci = &a->plci[i-1];
3478 plci->appl = appl;
3479 plci->command = _MANUFACTURER_R;
3480 plci->m_command = command;
3481 plci->number = Number;
3482 plci->State = LOCAL_CONNECT;
3483 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3484 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3486 if((ch==1 || ch==2) && (dir<=2)) {
3487 chi[1] = (byte)(0x80|ch);
3488 lli[1] = 0;
3489 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3490 switch(codec)
3492 case 0:
3493 Info = add_b1(plci,&m_parms[3],0,0);
3494 break;
3495 case 1:
3496 add_p(plci,CAI,codec_cai);
3497 break;
3498 /* manual 'swich on' to the codec support without signalling */
3499 /* first 'assign plci' with this function, then use */
3500 case 2:
3501 if(AdvCodecSupport(a, plci, appl, 0) ) {
3502 Info = _RESOURCE_ERROR;
3504 else {
3505 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3506 lli[1] = 0x10; /* local call codec stream */
3508 break;
3511 plci->State = LOCAL_CONNECT;
3512 plci->manufacturer = true;
3513 plci->command = _MANUFACTURER_R;
3514 plci->m_command = command;
3515 plci->number = Number;
3517 if(!Info)
3519 add_p(plci,LLI,lli);
3520 add_p(plci,CHI,chi);
3521 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3522 sig_req(plci,ASSIGN,DSIG_ID);
3524 if(!codec)
3526 Info = add_b23(plci,&m_parms[3]);
3527 if(!Info)
3529 nl_req_ncci(plci,ASSIGN,0);
3530 send_req(plci);
3533 if(!Info)
3535 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3536 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3538 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3539 plci->spoofed_msg = AWAITING_MANUF_CON;
3540 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3541 plci->command = 0;
3542 send_req(plci);
3543 return false;
3545 if(dir==1) {
3546 sig_req(plci,CALL_REQ,0);
3548 else if(!dir){
3549 sig_req(plci,LISTEN_REQ,0);
3551 send_req(plci);
3553 else
3555 sendf(appl,
3556 _MANUFACTURER_R|CONFIRM,
3558 Number,
3559 "dww",_DI_MANU_ID,command,Info);
3560 return 2;
3565 else Info = _OUT_OF_PLCI;
3566 break;
3568 case _DI_IDI_CTRL:
3569 if(!plci)
3571 Info = _WRONG_IDENTIFIER;
3572 break;
3574 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3575 Info = _WRONG_MESSAGE_FORMAT;
3576 break;
3578 req = m_parms[0].info[0];
3579 plci->command = _MANUFACTURER_R;
3580 plci->m_command = command;
3581 plci->number = Number;
3582 if(req==CALL_REQ)
3584 plci->b_channel = getChannel(&m_parms[1]);
3585 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3586 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3588 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3589 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3590 plci->command = 0;
3591 break;
3594 else if(req==LAW_REQ)
3596 plci->cr_enquiry = true;
3598 add_ss(plci,FTY,&m_parms[1]);
3599 sig_req(plci,req,0);
3600 send_req(plci);
3601 if(req==HANGUP)
3603 if (plci->NL.Id && !plci->nl_remove_id)
3605 if (plci->channels)
3607 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3609 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3611 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3612 cleanup_ncci_data (plci, ncci);
3613 nl_req_ncci(plci,N_DISC,(byte)ncci);
3617 mixer_remove (plci);
3618 nl_req_ncci(plci,REMOVE,0);
3619 send_req(plci);
3622 break;
3624 case _DI_SIG_CTRL:
3625 /* signalling control for loop activation B-channel */
3626 if(!plci)
3628 Info = _WRONG_IDENTIFIER;
3629 break;
3631 if(m->length){
3632 plci->command = _MANUFACTURER_R;
3633 plci->number = Number;
3634 add_ss(plci,FTY,m);
3635 sig_req(plci,SIG_CTRL,0);
3636 send_req(plci);
3638 else Info = _WRONG_MESSAGE_FORMAT;
3639 break;
3641 case _DI_RXT_CTRL:
3642 /* activation control for receiver/transmitter B-channel */
3643 if(!plci)
3645 Info = _WRONG_IDENTIFIER;
3646 break;
3648 if(m->length){
3649 plci->command = _MANUFACTURER_R;
3650 plci->number = Number;
3651 add_ss(plci,FTY,m);
3652 sig_req(plci,DSP_CTRL,0);
3653 send_req(plci);
3655 else Info = _WRONG_MESSAGE_FORMAT;
3656 break;
3658 case _DI_ADV_CODEC:
3659 case _DI_DSP_CTRL:
3660 /* TEL_CTRL commands to support non standard adjustments: */
3661 /* Ring on/off, Handset micro volume, external micro vol. */
3662 /* handset+external speaker volume, receiver+transm. gain,*/
3663 /* handsfree on (hookinfo off), set mixer command */
3665 if(command == _DI_ADV_CODEC)
3667 if(!a->AdvCodecPLCI) {
3668 Info = _WRONG_STATE;
3669 break;
3671 v_plci = a->AdvCodecPLCI;
3673 else
3675 if (plci
3676 && (m->length >= 3)
3677 && (m->info[1] == 0x1c)
3678 && (m->info[2] >= 1))
3680 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3682 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3684 Info = _WRONG_STATE;
3685 break;
3687 a->adv_voice_coef_length = m->info[2] - 1;
3688 if (a->adv_voice_coef_length > m->length - 3)
3689 a->adv_voice_coef_length = (byte)(m->length - 3);
3690 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3691 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3692 for (i = 0; i < a->adv_voice_coef_length; i++)
3693 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3694 if (plci->B1_facilities & B1_FACILITY_VOICE)
3695 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3696 break;
3698 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3700 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3702 Info = _FACILITY_NOT_SUPPORTED;
3703 break;
3706 plci->dtmf_parameter_length = m->info[2] - 1;
3707 if (plci->dtmf_parameter_length > m->length - 3)
3708 plci->dtmf_parameter_length = (byte)(m->length - 3);
3709 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3710 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3711 for (i = 0; i < plci->dtmf_parameter_length; i++)
3712 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3713 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3714 dtmf_parameter_write (plci);
3715 break;
3719 v_plci = plci;
3722 if(!v_plci)
3724 Info = _WRONG_IDENTIFIER;
3725 break;
3727 if(m->length){
3728 add_ss(v_plci,FTY,m);
3729 sig_req(v_plci,TEL_CTRL,0);
3730 send_req(v_plci);
3732 else Info = _WRONG_MESSAGE_FORMAT;
3734 break;
3736 case _DI_OPTIONS_REQUEST:
3737 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3738 Info = _WRONG_MESSAGE_FORMAT;
3739 break;
3741 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3743 Info = _FACILITY_NOT_SUPPORTED;
3744 break;
3746 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3747 break;
3751 default:
3752 Info = _WRONG_MESSAGE_FORMAT;
3753 break;
3757 sendf(appl,
3758 _MANUFACTURER_R|CONFIRM,
3760 Number,
3761 "dww",_DI_MANU_ID,command,Info);
3762 return false;
3766 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3767 PLCI *plci, APPL *appl, API_PARSE *msg)
3769 word indication;
3771 API_PARSE m_parms[3];
3772 API_PARSE *ncpi;
3773 API_PARSE fax_parms[9];
3774 word i;
3775 byte len;
3778 dbug(1,dprintf("manufacturer_res"));
3780 if ((msg[0].length == 0)
3781 || (msg[1].length == 0)
3782 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3784 return false;
3786 indication = GET_WORD(msg[1].info);
3787 switch (indication)
3790 case _DI_NEGOTIATE_B3:
3791 if(!plci)
3792 break;
3793 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3794 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3796 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3797 break;
3799 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3801 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3802 break;
3804 ncpi = &m_parms[1];
3805 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3806 if (plci->fax_connect_info_length < len)
3808 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3809 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3811 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3813 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3815 else
3817 if (plci->fax_connect_info_length <= len)
3818 plci->fax_connect_info_buffer[len] = 0;
3819 len += 1 + plci->fax_connect_info_buffer[len];
3820 if (plci->fax_connect_info_length <= len)
3821 plci->fax_connect_info_buffer[len] = 0;
3822 len += 1 + plci->fax_connect_info_buffer[len];
3823 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3824 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3825 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3826 for (i = 0; i < fax_parms[7].length; i++)
3827 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3829 plci->fax_connect_info_length = len;
3830 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3831 start_internal_command (Id, plci, fax_edata_ack_command);
3832 break;
3835 return false;
3838 /*------------------------------------------------------------------*/
3839 /* IDI callback function */
3840 /*------------------------------------------------------------------*/
3842 void callback(ENTITY * e)
3844 DIVA_CAPI_ADAPTER * a;
3845 APPL * appl;
3846 PLCI * plci;
3847 CAPI_MSG *m;
3848 word i, j;
3849 byte rc;
3850 byte ch;
3851 byte req;
3852 byte global_req;
3853 int no_cancel_rc;
3855 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3856 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3858 a = &(adapter[(byte)e->user[0]]);
3859 plci = &(a->plci[e->user[1]]);
3860 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3863 If new protocol code and new XDI is used then CAPI should work
3864 fully in accordance with IDI cpec an look on callback field instead
3865 of Rc field for return codes.
3867 if (((e->complete == 0xff) && no_cancel_rc) ||
3868 (e->Rc && !no_cancel_rc)) {
3869 rc = e->Rc;
3870 ch = e->RcCh;
3871 req = e->Req;
3872 e->Rc = 0;
3874 if (e->user[0] & 0x8000)
3877 If REMOVE request was sent then we have to wait until
3878 return code with Id set to zero arrives.
3879 All other return codes should be ignored.
3881 if (req == REMOVE)
3883 if (e->Id)
3885 dbug(1,dprintf("cancel RC in REMOVE state"));
3886 return;
3888 channel_flow_control_remove (plci);
3889 for (i = 0; i < 256; i++)
3891 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3892 a->FlowControlIdTable[i] = 0;
3894 plci->nl_remove_id = 0;
3895 if (plci->rx_dma_descriptor > 0) {
3896 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3897 plci->rx_dma_descriptor = 0;
3900 if (rc == OK_FC)
3902 a->FlowControlIdTable[ch] = e->Id;
3903 a->FlowControlSkipTable[ch] = 0;
3905 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3906 a->ch_flow_plci[ch] = plci->Id;
3907 plci->nl_req = 0;
3909 else
3912 Cancel return codes self, if feature was requested
3914 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3915 a->FlowControlIdTable[ch] = 0;
3916 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3917 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3918 return;
3922 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3924 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3925 if (ch == e->ReqCh)
3926 plci->nl_req = 0;
3928 else
3929 plci->nl_req = 0;
3931 if (plci->nl_req)
3932 control_rc (plci, 0, rc, ch, 0, true);
3933 else
3935 if (req == N_XON)
3937 channel_x_on (plci, ch);
3938 if (plci->internal_command)
3939 control_rc (plci, req, rc, ch, 0, true);
3941 else
3943 if (plci->nl_global_req)
3945 global_req = plci->nl_global_req;
3946 plci->nl_global_req = 0;
3947 if (rc != ASSIGN_OK) {
3948 e->Id = 0;
3949 if (plci->rx_dma_descriptor > 0) {
3950 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3951 plci->rx_dma_descriptor = 0;
3954 channel_xmit_xon (plci);
3955 control_rc (plci, 0, rc, ch, global_req, true);
3957 else if (plci->data_sent)
3959 channel_xmit_xon (plci);
3960 plci->data_sent = false;
3961 plci->NL.XNum = 1;
3962 data_rc (plci, ch);
3963 if (plci->internal_command)
3964 control_rc (plci, req, rc, ch, 0, true);
3966 else
3968 channel_xmit_xon (plci);
3969 control_rc (plci, req, rc, ch, 0, true);
3974 else
3977 If REMOVE request was sent then we have to wait until
3978 return code with Id set to zero arrives.
3979 All other return codes should be ignored.
3981 if (req == REMOVE)
3983 if (e->Id)
3985 dbug(1,dprintf("cancel RC in REMOVE state"));
3986 return;
3988 plci->sig_remove_id = 0;
3990 plci->sig_req = 0;
3991 if (plci->sig_global_req)
3993 global_req = plci->sig_global_req;
3994 plci->sig_global_req = 0;
3995 if (rc != ASSIGN_OK)
3996 e->Id = 0;
3997 channel_xmit_xon (plci);
3998 control_rc (plci, 0, rc, ch, global_req, false);
4000 else
4002 channel_xmit_xon (plci);
4003 control_rc (plci, req, rc, ch, 0, false);
4007 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4008 same callback. Also if new XDI and protocol code used then jump
4009 direct to finish.
4011 if (no_cancel_rc) {
4012 channel_xmit_xon(plci);
4013 goto capi_callback_suffix;
4017 channel_xmit_xon(plci);
4019 if (e->Ind) {
4020 if (e->user[0] &0x8000) {
4021 byte Ind = e->Ind & 0x0f;
4022 byte Ch = e->IndCh;
4023 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4024 (a->ch_flow_plci[Ch] == plci->Id)) {
4025 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4026 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4028 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4030 nl_ind(plci);
4031 if ((e->RNR != 1) &&
4032 (a->ch_flow_plci[Ch] == plci->Id) &&
4033 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4034 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4035 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4037 } else {
4038 sig_ind(plci);
4040 e->Ind = 0;
4043 capi_callback_suffix:
4045 while (!plci->req_in
4046 && !plci->internal_command
4047 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4049 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4051 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4053 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4054 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4055 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4056 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4057 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4059 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4060 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4062 else
4064 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4066 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4068 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4069 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4071 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4073 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4074 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4076 i = api_put (appl, m);
4077 if (i != 0)
4079 if (m->header.command == _DATA_B3_R)
4081 TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4083 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4084 break;
4087 if (plci->li_notify_update)
4089 plci->li_notify_update = false;
4090 mixer_notify_update (plci, false);
4094 send_data(plci);
4095 send_req(plci);
4099 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4100 byte nl_rc)
4102 dword Id;
4103 dword rId;
4104 word Number;
4105 word Info=0;
4106 word i;
4107 word ncci;
4108 DIVA_CAPI_ADAPTER * a;
4109 APPL * appl;
4110 PLCI * rplci;
4111 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4112 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4114 if (!plci) {
4115 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4116 return;
4118 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4119 if(plci->req_in!=plci->req_out)
4121 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4123 dbug(1,dprintf("req_1return"));
4124 return;
4126 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4128 plci->req_in = plci->req_in_start = plci->req_out = 0;
4129 dbug(1,dprintf("control_rc"));
4131 appl = plci->appl;
4132 a = plci->adapter;
4133 ncci = a->ch_ncci[ch];
4134 if(appl)
4136 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4137 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4138 Number = plci->number;
4139 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));
4140 dbug(1,dprintf("channels=0x%x",plci->channels));
4141 if (plci_remove_check(plci))
4142 return;
4143 if(req==REMOVE && rc==ASSIGN_OK)
4145 sig_req(plci,HANGUP,0);
4146 sig_req(plci,REMOVE,0);
4147 send_req(plci);
4149 if(plci->command)
4151 switch(plci->command)
4153 case C_HOLD_REQ:
4154 dbug(1,dprintf("HoldRC=0x%x",rc));
4155 SSparms[1] = (byte)S_HOLD;
4156 if(rc!=OK)
4158 plci->SuppState = IDLE;
4159 Info = 0x2001;
4161 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4162 break;
4164 case C_RETRIEVE_REQ:
4165 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4166 SSparms[1] = (byte)S_RETRIEVE;
4167 if(rc!=OK)
4169 plci->SuppState = CALL_HELD;
4170 Info = 0x2001;
4172 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4173 break;
4175 case _INFO_R:
4176 dbug(1,dprintf("InfoRC=0x%x",rc));
4177 if(rc!=OK) Info=_WRONG_STATE;
4178 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4179 break;
4181 case _CONNECT_R:
4182 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4183 if (plci->State == INC_DIS_PENDING)
4184 break;
4185 if(plci->Sig.Id!=0xff)
4187 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4188 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4190 dbug(1,dprintf("No more IDs/Call_Req failed"));
4191 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4192 plci_remove(plci);
4193 plci->State = IDLE;
4194 break;
4196 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4197 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4199 else /* D-ch activation */
4201 if (rc != ASSIGN_OK)
4203 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4204 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4205 plci_remove(plci);
4206 plci->State = IDLE;
4207 break;
4209 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4210 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4211 plci->State = INC_ACT_PENDING;
4213 break;
4215 case _CONNECT_I|RESPONSE:
4216 if (plci->State != INC_DIS_PENDING)
4217 plci->State = INC_CON_ACCEPT;
4218 break;
4220 case _DISCONNECT_R:
4221 if (plci->State == INC_DIS_PENDING)
4222 break;
4223 if(plci->Sig.Id!=0xff)
4225 plci->State = OUTG_DIS_PENDING;
4226 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4228 break;
4230 case SUSPEND_REQ:
4231 break;
4233 case RESUME_REQ:
4234 break;
4236 case _CONNECT_B3_R:
4237 if(rc!=OK)
4239 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4240 break;
4242 ncci = get_ncci (plci, ch, 0);
4243 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4244 plci->channels++;
4245 if(req==N_RESET)
4247 a->ncci_state[ncci] = INC_ACT_PENDING;
4248 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4249 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4251 else
4253 a->ncci_state[ncci] = OUTG_CON_PENDING;
4254 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4256 break;
4258 case _CONNECT_B3_I|RESPONSE:
4259 break;
4261 case _RESET_B3_R:
4262 /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4263 break;
4265 case _DISCONNECT_B3_R:
4266 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4267 break;
4269 case _MANUFACTURER_R:
4270 break;
4272 case PERM_LIST_REQ:
4273 if(rc!=OK)
4275 Info = _WRONG_IDENTIFIER;
4276 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4277 plci_remove(plci);
4279 else
4280 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4281 break;
4283 default:
4284 break;
4286 plci->command = 0;
4288 else if (plci->internal_command)
4290 switch(plci->internal_command)
4292 case BLOCK_PLCI:
4293 return;
4295 case GET_MWI_STATE:
4296 if(rc==OK) /* command supported, wait for indication */
4298 return;
4300 plci_remove(plci);
4301 break;
4303 /* Get Supported Services */
4304 case GETSERV_REQ_PEND:
4305 if(rc==OK) /* command supported, wait for indication */
4307 break;
4309 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4310 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4311 plci_remove(plci);
4312 break;
4314 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4315 case INTERR_NUMBERS_REQ_PEND:
4316 case CF_START_PEND: /* Call Forwarding Start pending */
4317 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4318 case CCBS_REQUEST_REQ_PEND:
4319 case CCBS_DEACTIVATE_REQ_PEND:
4320 case CCBS_INTERROGATE_REQ_PEND:
4321 switch(plci->internal_command)
4323 case INTERR_DIVERSION_REQ_PEND:
4324 SSparms[1] = S_INTERROGATE_DIVERSION;
4325 break;
4326 case INTERR_NUMBERS_REQ_PEND:
4327 SSparms[1] = S_INTERROGATE_NUMBERS;
4328 break;
4329 case CF_START_PEND:
4330 SSparms[1] = S_CALL_FORWARDING_START;
4331 break;
4332 case CF_STOP_PEND:
4333 SSparms[1] = S_CALL_FORWARDING_STOP;
4334 break;
4335 case CCBS_REQUEST_REQ_PEND:
4336 SSparms[1] = S_CCBS_REQUEST;
4337 break;
4338 case CCBS_DEACTIVATE_REQ_PEND:
4339 SSparms[1] = S_CCBS_DEACTIVATE;
4340 break;
4341 case CCBS_INTERROGATE_REQ_PEND:
4342 SSparms[1] = S_CCBS_INTERROGATE;
4343 break;
4345 if(global_req==ASSIGN)
4347 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4348 return;
4350 if(!plci->appl) break;
4351 if(rc==ISDN_GUARD_REJ)
4353 Info = _CAPI_GUARD_ERROR;
4355 else if(rc!=OK)
4357 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4359 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4360 plci->number,"wws",Info,(word)3,SSparms);
4361 if(Info) plci_remove(plci);
4362 break;
4364 /* 3pty conference pending */
4365 case PTY_REQ_PEND:
4366 if(!plci->relatedPTYPLCI) break;
4367 rplci = plci->relatedPTYPLCI;
4368 SSparms[1] = plci->ptyState;
4369 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4370 if(rplci->tel) rId|=EXT_CONTROLLER;
4371 if(rc!=OK)
4373 Info = 0x300E; /* not supported */
4374 plci->relatedPTYPLCI = NULL;
4375 plci->ptyState = 0;
4377 sendf(rplci->appl,
4378 _FACILITY_R|CONFIRM,
4379 rId,
4380 plci->number,
4381 "wws",Info,(word)3,SSparms);
4382 break;
4384 /* Explicit Call Transfer pending */
4385 case ECT_REQ_PEND:
4386 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4387 if(!plci->relatedPTYPLCI) break;
4388 rplci = plci->relatedPTYPLCI;
4389 SSparms[1] = S_ECT;
4390 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4391 if(rplci->tel) rId|=EXT_CONTROLLER;
4392 if(rc!=OK)
4394 Info = 0x300E; /* not supported */
4395 plci->relatedPTYPLCI = NULL;
4396 plci->ptyState = 0;
4398 sendf(rplci->appl,
4399 _FACILITY_R|CONFIRM,
4400 rId,
4401 plci->number,
4402 "wws",Info,(word)3,SSparms);
4403 break;
4405 case _MANUFACTURER_R:
4406 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4407 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4409 dbug(1,dprintf("No more IDs"));
4410 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4411 plci_remove(plci); /* after codec init, internal codec commands pending */
4413 break;
4415 case _CONNECT_R:
4416 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4417 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4419 dbug(1,dprintf("No more IDs"));
4420 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4421 plci_remove(plci); /* after codec init, internal codec commands pending */
4423 break;
4425 case PERM_COD_HOOK: /* finished with Hook_Ind */
4426 return;
4428 case PERM_COD_CALL:
4429 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4430 plci->internal_command = PERM_COD_CONN_PEND;
4431 return;
4433 case PERM_COD_ASSIGN:
4434 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4435 if(rc!=ASSIGN_OK) break;
4436 sig_req(plci,CALL_REQ,0);
4437 send_req(plci);
4438 plci->internal_command = PERM_COD_CALL;
4439 return;
4441 /* Null Call Reference Request pending */
4442 case C_NCR_FAC_REQ:
4443 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4444 if(global_req==ASSIGN)
4446 if(rc==ASSIGN_OK)
4448 return;
4450 else
4452 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4453 appl->NullCREnable = false;
4454 plci_remove(plci);
4457 else if(req==NCR_FACILITY)
4459 if(rc==OK)
4461 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4463 else
4465 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4466 appl->NullCREnable = false;
4468 plci_remove(plci);
4470 break;
4472 case HOOK_ON_REQ:
4473 if(plci->channels)
4475 if(a->ncci_state[ncci]==CONNECTED)
4477 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4478 cleanup_ncci_data (plci, ncci);
4479 nl_req_ncci(plci,N_DISC,(byte)ncci);
4481 break;
4483 break;
4485 case HOOK_OFF_REQ:
4486 if (plci->State == INC_DIS_PENDING)
4487 break;
4488 sig_req(plci,CALL_REQ,0);
4489 send_req(plci);
4490 plci->State=OUTG_CON_PENDING;
4491 break;
4494 case MWI_ACTIVATE_REQ_PEND:
4495 case MWI_DEACTIVATE_REQ_PEND:
4496 if(global_req == ASSIGN && rc==ASSIGN_OK)
4498 dbug(1,dprintf("MWI_REQ assigned"));
4499 return;
4501 else if(rc!=OK)
4503 if(rc==WRONG_IE)
4505 Info = 0x2007; /* Illegal message parameter coding */
4506 dbug(1,dprintf("MWI_REQ invalid parameter"));
4508 else
4510 Info = 0x300B; /* not supported */
4511 dbug(1,dprintf("MWI_REQ not supported"));
4513 /* 0x3010: Request not allowed in this state */
4514 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4517 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4519 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4521 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4523 if(plci->cr_enquiry)
4525 sendf(plci->appl,
4526 _FACILITY_R|CONFIRM,
4527 Id&0xf,
4528 plci->number,
4529 "wws",Info,(word)3,SSparms);
4530 if(rc!=OK) plci_remove(plci);
4532 else
4534 sendf(plci->appl,
4535 _FACILITY_R|CONFIRM,
4537 plci->number,
4538 "wws",Info,(word)3,SSparms);
4540 break;
4542 case CONF_BEGIN_REQ_PEND:
4543 case CONF_ADD_REQ_PEND:
4544 case CONF_SPLIT_REQ_PEND:
4545 case CONF_DROP_REQ_PEND:
4546 case CONF_ISOLATE_REQ_PEND:
4547 case CONF_REATTACH_REQ_PEND:
4548 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4549 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4550 rplci = plci;
4551 rId = Id;
4552 switch(plci->internal_command)
4554 case CONF_BEGIN_REQ_PEND:
4555 SSparms[1] = S_CONF_BEGIN;
4556 break;
4557 case CONF_ADD_REQ_PEND:
4558 SSparms[1] = S_CONF_ADD;
4559 rplci = plci->relatedPTYPLCI;
4560 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4561 break;
4562 case CONF_SPLIT_REQ_PEND:
4563 SSparms[1] = S_CONF_SPLIT;
4564 break;
4565 case CONF_DROP_REQ_PEND:
4566 SSparms[1] = S_CONF_DROP;
4567 break;
4568 case CONF_ISOLATE_REQ_PEND:
4569 SSparms[1] = S_CONF_ISOLATE;
4570 break;
4571 case CONF_REATTACH_REQ_PEND:
4572 SSparms[1] = S_CONF_REATTACH;
4573 break;
4576 if(rc!=OK)
4578 Info = 0x300E; /* not supported */
4579 plci->relatedPTYPLCI = NULL;
4580 plci->ptyState = 0;
4582 sendf(rplci->appl,
4583 _FACILITY_R|CONFIRM,
4584 rId,
4585 plci->number,
4586 "wws",Info,(word)3,SSparms);
4587 break;
4589 case VSWITCH_REQ_PEND:
4590 if(rc!=OK)
4592 if(plci->relatedPTYPLCI)
4594 plci->relatedPTYPLCI->vswitchstate=0;
4595 plci->relatedPTYPLCI->vsprot=0;
4596 plci->relatedPTYPLCI->vsprotdialect=0;
4598 plci->vswitchstate=0;
4599 plci->vsprot=0;
4600 plci->vsprotdialect=0;
4602 else
4604 if(plci->relatedPTYPLCI &&
4605 plci->vswitchstate==1 &&
4606 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4607 plci->vswitchstate=3;
4609 break;
4611 /* Call Deflection Request pending (SSCT) */
4612 case CD_REQ_PEND:
4613 SSparms[1] = S_CALL_DEFLECTION;
4614 if(rc!=OK)
4616 Info = 0x300E; /* not supported */
4617 plci->appl->CDEnable = 0;
4619 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4620 plci->number,"wws",Info,(word)3,SSparms);
4621 break;
4623 case RTP_CONNECT_B3_REQ_COMMAND_2:
4624 if (rc == OK)
4626 ncci = get_ncci (plci, ch, 0);
4627 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4628 plci->channels++;
4629 a->ncci_state[ncci] = OUTG_CON_PENDING;
4632 default:
4633 if (plci->internal_command_queue[0])
4635 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4636 if (plci->internal_command)
4637 return;
4639 break;
4641 next_internal_command (Id, plci);
4644 else /* appl==0 */
4646 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4647 if(plci->tel) Id|=EXT_CONTROLLER;
4649 switch(plci->internal_command)
4651 case BLOCK_PLCI:
4652 return;
4654 case START_L1_SIG_ASSIGN_PEND:
4655 case REM_L1_SIG_ASSIGN_PEND:
4656 if(global_req == ASSIGN)
4658 break;
4660 else
4662 dbug(1,dprintf("***L1 Req rem PLCI"));
4663 plci->internal_command = 0;
4664 sig_req(plci,REMOVE,0);
4665 send_req(plci);
4667 break;
4669 /* Call Deflection Request pending, just no appl ptr assigned */
4670 case CD_REQ_PEND:
4671 SSparms[1] = S_CALL_DEFLECTION;
4672 if(rc!=OK)
4674 Info = 0x300E; /* not supported */
4676 for(i=0; i<max_appl; i++)
4678 if(application[i].CDEnable)
4680 if(!application[i].Id) application[i].CDEnable = 0;
4681 else
4683 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4684 plci->number,"wws",Info,(word)3,SSparms);
4685 if(Info) application[i].CDEnable = 0;
4689 plci->internal_command = 0;
4690 break;
4692 case PERM_COD_HOOK: /* finished with Hook_Ind */
4693 return;
4695 case PERM_COD_CALL:
4696 plci->internal_command = PERM_COD_CONN_PEND;
4697 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4698 return;
4700 case PERM_COD_ASSIGN:
4701 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4702 plci->internal_command = 0;
4703 if(rc!=ASSIGN_OK) break;
4704 plci->internal_command = PERM_COD_CALL;
4705 sig_req(plci,CALL_REQ,0);
4706 send_req(plci);
4707 return;
4709 case LISTEN_SIG_ASSIGN_PEND:
4710 if(rc == ASSIGN_OK)
4712 plci->internal_command = 0;
4713 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4714 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4715 sig_req(plci,INDICATE_REQ,0);
4716 send_req(plci);
4718 else
4720 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4721 a->listen_active--;
4722 plci_remove(plci);
4723 plci->State = IDLE;
4725 break;
4727 case USELAW_REQ:
4728 if(global_req == ASSIGN)
4730 if (rc==ASSIGN_OK)
4732 sig_req(plci,LAW_REQ,0);
4733 send_req(plci);
4734 dbug(1,dprintf("Auto-Law assigned"));
4736 else
4738 dbug(1,dprintf("Auto-Law assign failed"));
4739 a->automatic_law = 3;
4740 plci->internal_command = 0;
4741 a->automatic_lawPLCI = NULL;
4743 break;
4745 else if(req == LAW_REQ && rc==OK)
4747 dbug(1,dprintf("Auto-Law initiated"));
4748 a->automatic_law = 2;
4749 plci->internal_command = 0;
4751 else
4753 dbug(1,dprintf("Auto-Law not supported"));
4754 a->automatic_law = 3;
4755 plci->internal_command = 0;
4756 sig_req(plci,REMOVE,0);
4757 send_req(plci);
4758 a->automatic_lawPLCI = NULL;
4760 break;
4762 plci_remove_check(plci);
4766 static void data_rc(PLCI *plci, byte ch)
4768 dword Id;
4769 DIVA_CAPI_ADAPTER * a;
4770 NCCI *ncci_ptr;
4771 DATA_B3_DESC *data;
4772 word ncci;
4774 if (plci->appl)
4776 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4777 a = plci->adapter;
4778 ncci = a->ch_ncci[ch];
4779 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4781 ncci_ptr = &(a->ncci[ncci]);
4782 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4783 if (ncci_ptr->data_pending)
4785 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4786 if (!(data->Flags &4) && a->ncci_state[ncci])
4788 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4789 if(plci->tel) Id|=EXT_CONTROLLER;
4790 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4791 "ww",data->Handle,0);
4793 (ncci_ptr->data_out)++;
4794 if (ncci_ptr->data_out == MAX_DATA_B3)
4795 ncci_ptr->data_out = 0;
4796 (ncci_ptr->data_pending)--;
4802 static void data_ack(PLCI *plci, byte ch)
4804 dword Id;
4805 DIVA_CAPI_ADAPTER * a;
4806 NCCI *ncci_ptr;
4807 word ncci;
4809 a = plci->adapter;
4810 ncci = a->ch_ncci[ch];
4811 ncci_ptr = &(a->ncci[ncci]);
4812 if (ncci_ptr->data_ack_pending)
4814 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4816 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4817 if(plci->tel) Id|=EXT_CONTROLLER;
4818 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4819 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4821 (ncci_ptr->data_ack_out)++;
4822 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4823 ncci_ptr->data_ack_out = 0;
4824 (ncci_ptr->data_ack_pending)--;
4828 static void sig_ind(PLCI *plci)
4830 dword x_Id;
4831 dword Id;
4832 dword rId;
4833 word Number = 0;
4834 word i;
4835 word cip;
4836 dword cip_mask;
4837 byte *ie;
4838 DIVA_CAPI_ADAPTER * a;
4839 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4840 #define MAXPARMSIDS 31
4841 byte * parms[MAXPARMSIDS];
4842 byte * add_i[4];
4843 byte * multi_fac_parms[MAX_MULTI_IE];
4844 byte * multi_pi_parms [MAX_MULTI_IE];
4845 byte * multi_ssext_parms [MAX_MULTI_IE];
4846 byte * multi_CiPN_parms [MAX_MULTI_IE];
4848 byte * multi_vswitch_parms [MAX_MULTI_IE];
4850 byte ai_len;
4851 byte *esc_chi = "";
4852 byte *esc_law = "";
4853 byte *pty_cai = "";
4854 byte *esc_cr = "";
4855 byte *esc_profile = "";
4857 byte facility[256];
4858 PLCI * tplci = NULL;
4859 byte chi[] = "\x02\x18\x01";
4860 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4861 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4862 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4863 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4864 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4865 /* (see Info_Mask Bit 4, first IE. then the message type) */
4866 word parms_id[] =
4867 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4868 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4869 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4870 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4871 /* 14 FTY repl by ESC_CHI */
4872 /* 18 PI repl by ESC_LAW */
4873 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4874 word multi_fac_id[] = {1, FTY};
4875 word multi_pi_id[] = {1, PI};
4876 word multi_CiPN_id[] = {1, OAD};
4877 word multi_ssext_id[] = {1, ESC_SSEXT};
4879 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4881 byte * cau;
4882 word ncci;
4883 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4884 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4885 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4886 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4887 byte force_mt_info = false;
4888 byte dir;
4889 dword d;
4890 word w;
4892 a = plci->adapter;
4893 Id = ((word)plci->Id<<8)|a->Id;
4894 PUT_WORD(&SS_Ind[4],0x0000);
4896 if (plci->sig_remove_id)
4898 plci->Sig.RNR = 2; /* discard */
4899 dbug(1,dprintf("SIG discard while remove pending"));
4900 return;
4902 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4903 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4904 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4905 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4907 plci->Sig.RNR = 1;
4908 return;
4910 if(plci->Sig.Ind==HANGUP && plci->channels)
4912 plci->Sig.RNR = 1;
4913 plci->hangup_flow_ctrl_timer++;
4914 /* recover the network layer after timeout */
4915 if(plci->hangup_flow_ctrl_timer==100)
4917 dbug(1,dprintf("Exceptional disc"));
4918 plci->Sig.RNR = 0;
4919 plci->hangup_flow_ctrl_timer = 0;
4920 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4922 if (a->ncci_plci[ncci] == plci->Id)
4924 cleanup_ncci_data (plci, ncci);
4925 if(plci->channels)plci->channels--;
4926 if (plci->appl)
4927 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4930 if (plci->appl)
4931 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4932 plci_remove(plci);
4933 plci->State=IDLE;
4935 return;
4938 /* do first parse the info with no OAD in, because OAD will be converted */
4939 /* first the multiple facility IE, then mult. progress ind. */
4940 /* then the parameters for the info_ind + conn_ind */
4941 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4942 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4943 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4945 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4947 IndParse(plci,parms_id,parms,0);
4948 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4949 esc_chi = parms[14];
4950 esc_law = parms[18];
4951 pty_cai = parms[24];
4952 esc_cr = parms[25];
4953 esc_profile = parms[27];
4954 if(esc_cr[0] && plci)
4956 if(plci->cr_enquiry && plci->appl)
4958 plci->cr_enquiry = false;
4959 /* d = MANU_ID */
4960 /* w = m_command */
4961 /* b = total length */
4962 /* b = indication type */
4963 /* b = length of all IEs */
4964 /* b = IE1 */
4965 /* S = IE1 length + cont. */
4966 /* b = IE2 */
4967 /* S = IE2 length + cont. */
4968 sendf(plci->appl,
4969 _MANUFACTURER_I,
4972 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4973 2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law);
4976 /* create the additional info structure */
4977 add_i[1] = parms[15]; /* KEY of additional info */
4978 add_i[2] = parms[11]; /* UUI of additional info */
4979 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4981 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4982 /* indication returns by the card if requested by the function */
4983 /* AutomaticLaw() after driver init */
4984 if (a->automatic_law<4)
4986 if(esc_law[0]){
4987 if(esc_law[2]){
4988 dbug(0,dprintf("u-Law selected"));
4989 a->u_law = 1;
4991 else {
4992 dbug(0,dprintf("a-Law selected"));
4993 a->u_law = 0;
4995 a->automatic_law = 4;
4996 if(plci==a->automatic_lawPLCI) {
4997 plci->internal_command = 0;
4998 sig_req(plci,REMOVE,0);
4999 send_req(plci);
5000 a->automatic_lawPLCI = NULL;
5003 if (esc_profile[0])
5005 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5006 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
5007 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
5008 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
5010 a->profile.Global_Options &= 0x000000ffL;
5011 a->profile.B1_Protocols &= 0x000003ffL;
5012 a->profile.B2_Protocols &= 0x00001fdfL;
5013 a->profile.B3_Protocols &= 0x000000b7L;
5015 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
5016 GL_BCHANNEL_OPERATION_SUPPORTED;
5017 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
5018 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
5019 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5020 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5021 a->man_profile.private_options = 0;
5023 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5025 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5026 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5030 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5031 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5032 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5033 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5036 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5037 a->man_profile.private_options |= 1L << PRIVATE_T38;
5040 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5041 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5044 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5045 a->man_profile.private_options |= 1L << PRIVATE_V18;
5048 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5049 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5052 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5053 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5056 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5057 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5060 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5061 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5064 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5065 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5068 else
5070 a->profile.Global_Options &= 0x0000007fL;
5071 a->profile.B1_Protocols &= 0x000003dfL;
5072 a->profile.B2_Protocols &= 0x00001adfL;
5073 a->profile.B3_Protocols &= 0x000000b7L;
5074 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5076 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5077 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5079 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5081 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5082 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5083 UnMapController (a->Id), a->profile.Global_Options,
5084 a->profile.B1_Protocols, a->profile.B2_Protocols,
5085 a->profile.B3_Protocols, a->manufacturer_features));
5087 /* codec plci for the handset/hook state support is just an internal id */
5088 if(plci!=a->AdvCodecPLCI)
5090 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5091 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5092 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5093 SendInfo(plci,Id, parms, force_mt_info);
5095 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5099 /* switch the codec to the b-channel */
5100 if(esc_chi[0] && plci && !plci->SuppState){
5101 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5102 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5103 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5104 if(plci->tel==ADV_VOICE && plci->appl) {
5105 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5109 if(plci->appl) Number = plci->appl->Number++;
5111 switch(plci->Sig.Ind) {
5112 /* Response to Get_Supported_Services request */
5113 case S_SUPPORTED:
5114 dbug(1,dprintf("S_Supported"));
5115 if(!plci->appl) break;
5116 if(pty_cai[0]==4)
5118 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5120 else
5122 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5124 PUT_WORD (&CF_Ind[1], 0);
5125 PUT_WORD (&CF_Ind[4], 0);
5126 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5127 plci_remove(plci);
5128 break;
5130 /* Supplementary Service rejected */
5131 case S_SERVICE_REJ:
5132 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5133 if(!pty_cai[0]) break;
5134 switch (pty_cai[5])
5136 case ECT_EXECUTE:
5137 case THREE_PTY_END:
5138 case THREE_PTY_BEGIN:
5139 if(!plci->relatedPTYPLCI) break;
5140 tplci = plci->relatedPTYPLCI;
5141 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5142 if(tplci->tel) rId|=EXT_CONTROLLER;
5143 if(pty_cai[5]==ECT_EXECUTE)
5145 PUT_WORD(&SS_Ind[1],S_ECT);
5147 plci->vswitchstate=0;
5148 plci->relatedPTYPLCI->vswitchstate=0;
5151 else
5153 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5155 if(pty_cai[2]!=0xff)
5157 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5159 else
5161 PUT_WORD(&SS_Ind[4],0x300E);
5163 plci->relatedPTYPLCI = NULL;
5164 plci->ptyState = 0;
5165 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5166 break;
5168 case CALL_DEFLECTION:
5169 if(pty_cai[2]!=0xff)
5171 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5173 else
5175 PUT_WORD(&SS_Ind[4],0x300E);
5177 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5178 for(i=0; i<max_appl; i++)
5180 if(application[i].CDEnable)
5182 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5183 application[i].CDEnable = false;
5186 break;
5188 case DEACTIVATION_DIVERSION:
5189 case ACTIVATION_DIVERSION:
5190 case DIVERSION_INTERROGATE_CFU:
5191 case DIVERSION_INTERROGATE_CFB:
5192 case DIVERSION_INTERROGATE_CFNR:
5193 case DIVERSION_INTERROGATE_NUM:
5194 case CCBS_REQUEST:
5195 case CCBS_DEACTIVATE:
5196 case CCBS_INTERROGATE:
5197 if(!plci->appl) break;
5198 if(pty_cai[2]!=0xff)
5200 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5202 else
5204 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5206 switch (pty_cai[5])
5208 case DEACTIVATION_DIVERSION:
5209 dbug(1,dprintf("Deact_Div"));
5210 Interr_Err_Ind[0]=0x9;
5211 Interr_Err_Ind[3]=0x6;
5212 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5213 break;
5214 case ACTIVATION_DIVERSION:
5215 dbug(1,dprintf("Act_Div"));
5216 Interr_Err_Ind[0]=0x9;
5217 Interr_Err_Ind[3]=0x6;
5218 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5219 break;
5220 case DIVERSION_INTERROGATE_CFU:
5221 case DIVERSION_INTERROGATE_CFB:
5222 case DIVERSION_INTERROGATE_CFNR:
5223 dbug(1,dprintf("Interr_Div"));
5224 Interr_Err_Ind[0]=0xa;
5225 Interr_Err_Ind[3]=0x7;
5226 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5227 break;
5228 case DIVERSION_INTERROGATE_NUM:
5229 dbug(1,dprintf("Interr_Num"));
5230 Interr_Err_Ind[0]=0xa;
5231 Interr_Err_Ind[3]=0x7;
5232 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5233 break;
5234 case CCBS_REQUEST:
5235 dbug(1,dprintf("CCBS Request"));
5236 Interr_Err_Ind[0]=0xd;
5237 Interr_Err_Ind[3]=0xa;
5238 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5239 break;
5240 case CCBS_DEACTIVATE:
5241 dbug(1,dprintf("CCBS Deactivate"));
5242 Interr_Err_Ind[0]=0x9;
5243 Interr_Err_Ind[3]=0x6;
5244 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5245 break;
5246 case CCBS_INTERROGATE:
5247 dbug(1,dprintf("CCBS Interrogate"));
5248 Interr_Err_Ind[0]=0xb;
5249 Interr_Err_Ind[3]=0x8;
5250 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5251 break;
5253 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5254 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5255 plci_remove(plci);
5256 break;
5257 case ACTIVATION_MWI:
5258 case DEACTIVATION_MWI:
5259 if(pty_cai[5]==ACTIVATION_MWI)
5261 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5263 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5265 if(pty_cai[2]!=0xff)
5267 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5269 else
5271 PUT_WORD(&SS_Ind[4],0x300E);
5274 if(plci->cr_enquiry)
5276 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5277 plci_remove(plci);
5279 else
5281 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5283 break;
5284 case CONF_ADD: /* ERROR */
5285 case CONF_BEGIN:
5286 case CONF_DROP:
5287 case CONF_ISOLATE:
5288 case CONF_REATTACH:
5289 CONF_Ind[0]=9;
5290 CONF_Ind[3]=6;
5291 switch(pty_cai[5])
5293 case CONF_BEGIN:
5294 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5295 plci->ptyState = 0;
5296 break;
5297 case CONF_DROP:
5298 CONF_Ind[0]=5;
5299 CONF_Ind[3]=2;
5300 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5301 plci->ptyState = CONNECTED;
5302 break;
5303 case CONF_ISOLATE:
5304 CONF_Ind[0]=5;
5305 CONF_Ind[3]=2;
5306 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5307 plci->ptyState = CONNECTED;
5308 break;
5309 case CONF_REATTACH:
5310 CONF_Ind[0]=5;
5311 CONF_Ind[3]=2;
5312 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5313 plci->ptyState = CONNECTED;
5314 break;
5315 case CONF_ADD:
5316 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5317 plci->relatedPTYPLCI = NULL;
5318 tplci=plci->relatedPTYPLCI;
5319 if(tplci) tplci->ptyState = CONNECTED;
5320 plci->ptyState = CONNECTED;
5321 break;
5324 if(pty_cai[2]!=0xff)
5326 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5328 else
5330 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5331 within the required time */
5334 PUT_DWORD(&CONF_Ind[6],0x0);
5335 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5336 break;
5338 break;
5340 /* Supplementary Service indicates success */
5341 case S_SERVICE:
5342 dbug(1,dprintf("Service_Ind"));
5343 PUT_WORD (&CF_Ind[4], 0);
5344 switch (pty_cai[5])
5346 case THREE_PTY_END:
5347 case THREE_PTY_BEGIN:
5348 case ECT_EXECUTE:
5349 if(!plci->relatedPTYPLCI) break;
5350 tplci = plci->relatedPTYPLCI;
5351 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5352 if(tplci->tel) rId|=EXT_CONTROLLER;
5353 if(pty_cai[5]==ECT_EXECUTE)
5355 PUT_WORD(&SS_Ind[1],S_ECT);
5357 if(plci->vswitchstate!=3)
5360 plci->ptyState = IDLE;
5361 plci->relatedPTYPLCI = NULL;
5362 plci->ptyState = 0;
5366 dbug(1,dprintf("ECT OK"));
5367 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5372 else
5374 switch (plci->ptyState)
5376 case S_3PTY_BEGIN:
5377 plci->ptyState = CONNECTED;
5378 dbug(1,dprintf("3PTY ON"));
5379 break;
5381 case S_3PTY_END:
5382 plci->ptyState = IDLE;
5383 plci->relatedPTYPLCI = NULL;
5384 plci->ptyState = 0;
5385 dbug(1,dprintf("3PTY OFF"));
5386 break;
5388 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5389 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5391 break;
5393 case CALL_DEFLECTION:
5394 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5395 for(i=0; i<max_appl; i++)
5397 if(application[i].CDEnable)
5399 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5400 application[i].CDEnable = false;
5403 break;
5405 case DEACTIVATION_DIVERSION:
5406 case ACTIVATION_DIVERSION:
5407 if(!plci->appl) break;
5408 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5409 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5410 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5411 plci_remove(plci);
5412 break;
5414 case DIVERSION_INTERROGATE_CFU:
5415 case DIVERSION_INTERROGATE_CFB:
5416 case DIVERSION_INTERROGATE_CFNR:
5417 case DIVERSION_INTERROGATE_NUM:
5418 case CCBS_REQUEST:
5419 case CCBS_DEACTIVATE:
5420 case CCBS_INTERROGATE:
5421 if(!plci->appl) break;
5422 switch (pty_cai[5])
5424 case DIVERSION_INTERROGATE_CFU:
5425 case DIVERSION_INTERROGATE_CFB:
5426 case DIVERSION_INTERROGATE_CFNR:
5427 dbug(1,dprintf("Interr_Div"));
5428 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5429 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430 break;
5431 case DIVERSION_INTERROGATE_NUM:
5432 dbug(1,dprintf("Interr_Num"));
5433 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5434 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5435 break;
5436 case CCBS_REQUEST:
5437 dbug(1,dprintf("CCBS Request"));
5438 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5439 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5440 break;
5441 case CCBS_DEACTIVATE:
5442 dbug(1,dprintf("CCBS Deactivate"));
5443 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5444 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5445 break;
5446 case CCBS_INTERROGATE:
5447 dbug(1,dprintf("CCBS Interrogate"));
5448 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5449 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5450 break;
5452 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5453 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5454 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5455 plci_remove(plci);
5456 break;
5458 case ACTIVATION_MWI:
5459 case DEACTIVATION_MWI:
5460 if(pty_cai[5]==ACTIVATION_MWI)
5462 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5464 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5465 if(plci->cr_enquiry)
5467 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5468 plci_remove(plci);
5470 else
5472 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5474 break;
5475 case MWI_INDICATION:
5476 if(pty_cai[0]>=0x12)
5478 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5479 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5480 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5481 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5483 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5485 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5486 plci_remove(plci);
5487 return;
5489 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5490 pty_cai[0]=0;
5492 else
5494 for(i=0; i<max_appl; i++)
5496 if(a->Notification_Mask[i]&SMASK_MWI)
5498 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5499 pty_cai[0]=0;
5504 if(!pty_cai[0])
5505 { /* acknowledge */
5506 facility[2]= 0; /* returncode */
5508 else facility[2]= 0xff;
5510 else
5512 /* reject */
5513 facility[2]= 0xff; /* returncode */
5515 facility[0]= 2;
5516 facility[1]= MWI_RESPONSE; /* Function */
5517 add_p(plci,CAI,facility);
5518 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5519 sig_req(plci,S_SERVICE,0);
5520 send_req(plci);
5521 plci->command = 0;
5522 next_internal_command (Id, plci);
5523 break;
5524 case CONF_ADD: /* OK */
5525 case CONF_BEGIN:
5526 case CONF_DROP:
5527 case CONF_ISOLATE:
5528 case CONF_REATTACH:
5529 case CONF_PARTYDISC:
5530 CONF_Ind[0]=9;
5531 CONF_Ind[3]=6;
5532 switch(pty_cai[5])
5534 case CONF_BEGIN:
5535 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5536 if(pty_cai[0]==6)
5538 d=pty_cai[6];
5539 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5541 else
5543 PUT_DWORD(&CONF_Ind[6],0x0);
5545 break;
5546 case CONF_ISOLATE:
5547 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5548 CONF_Ind[0]=5;
5549 CONF_Ind[3]=2;
5550 break;
5551 case CONF_REATTACH:
5552 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5553 CONF_Ind[0]=5;
5554 CONF_Ind[3]=2;
5555 break;
5556 case CONF_DROP:
5557 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5558 CONF_Ind[0]=5;
5559 CONF_Ind[3]=2;
5560 break;
5561 case CONF_ADD:
5562 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5563 d=pty_cai[6];
5564 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5565 tplci=plci->relatedPTYPLCI;
5566 if(tplci) tplci->ptyState = CONNECTED;
5567 break;
5568 case CONF_PARTYDISC:
5569 CONF_Ind[0]=7;
5570 CONF_Ind[3]=4;
5571 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5572 d=pty_cai[6];
5573 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5574 break;
5576 plci->ptyState = CONNECTED;
5577 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5578 break;
5579 case CCBS_INFO_RETAIN:
5580 case CCBS_ERASECALLLINKAGEID:
5581 case CCBS_STOP_ALERTING:
5582 CONF_Ind[0]=5;
5583 CONF_Ind[3]=2;
5584 switch(pty_cai[5])
5586 case CCBS_INFO_RETAIN:
5587 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5588 break;
5589 case CCBS_STOP_ALERTING:
5590 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5591 break;
5592 case CCBS_ERASECALLLINKAGEID:
5593 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5594 CONF_Ind[0]=7;
5595 CONF_Ind[3]=4;
5596 CONF_Ind[6]=0;
5597 CONF_Ind[7]=0;
5598 break;
5600 w=pty_cai[6];
5601 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5603 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5605 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5607 else
5609 for(i=0; i<max_appl; i++)
5610 if(a->Notification_Mask[i]&SMASK_CCBS)
5611 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5613 break;
5615 break;
5616 case CALL_HOLD_REJ:
5617 cau = parms[7];
5618 if(cau)
5620 i = _L3_CAUSE | cau[2];
5621 if(cau[2]==0) i = 0x3603;
5623 else
5625 i = 0x3603;
5627 PUT_WORD(&SS_Ind[1],S_HOLD);
5628 PUT_WORD(&SS_Ind[4],i);
5629 if(plci->SuppState == HOLD_REQUEST)
5631 plci->SuppState = IDLE;
5632 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5634 break;
5636 case CALL_HOLD_ACK:
5637 if(plci->SuppState == HOLD_REQUEST)
5639 plci->SuppState = CALL_HELD;
5640 CodecIdCheck(a, plci);
5641 start_internal_command (Id, plci, hold_save_command);
5643 break;
5645 case CALL_RETRIEVE_REJ:
5646 cau = parms[7];
5647 if(cau)
5649 i = _L3_CAUSE | cau[2];
5650 if(cau[2]==0) i = 0x3603;
5652 else
5654 i = 0x3603;
5656 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5657 PUT_WORD(&SS_Ind[4],i);
5658 if(plci->SuppState == RETRIEVE_REQUEST)
5660 plci->SuppState = CALL_HELD;
5661 CodecIdCheck(a, plci);
5662 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5664 break;
5666 case CALL_RETRIEVE_ACK:
5667 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5668 if(plci->SuppState == RETRIEVE_REQUEST)
5670 plci->SuppState = IDLE;
5671 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5672 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5673 if(plci->tel)
5675 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5676 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5677 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5678 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5680 dbug(1,dprintf("Get B-ch"));
5681 start_internal_command (Id, plci, retrieve_restore_command);
5683 else
5684 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5686 else
5687 start_internal_command (Id, plci, retrieve_restore_command);
5689 break;
5691 case INDICATE_IND:
5692 if(plci->State != LISTENING) {
5693 sig_req(plci,HANGUP,0);
5694 send_req(plci);
5695 break;
5697 cip = find_cip(a,parms[4],parms[6]);
5698 cip_mask = 1L<<cip;
5699 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5700 clear_c_ind_mask (plci);
5701 if (!remove_started && !a->adapter_disabled)
5703 set_c_ind_mask_bit (plci, MAX_APPL);
5704 group_optimization(a, plci);
5705 for(i=0; i<max_appl; i++) {
5706 if(application[i].Id
5707 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5708 && CPN_filter_ok(parms[0],a,i)
5709 && test_group_ind_mask_bit (plci, i) ) {
5710 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5711 set_c_ind_mask_bit (plci, i);
5712 dump_c_ind_mask (plci);
5713 plci->State = INC_CON_PENDING;
5714 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5715 CALL_DIR_IN | CALL_DIR_ANSWER;
5716 if(esc_chi[0]) {
5717 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5718 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5720 /* if a listen on the ext controller is done, check if hook states */
5721 /* are supported or if just a on board codec must be activated */
5722 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5723 if(a->profile.Global_Options & HANDSET)
5724 plci->tel = ADV_VOICE;
5725 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5726 plci->tel = CODEC;
5727 if(plci->tel) Id|=EXT_CONTROLLER;
5728 a->codec_listen[i] = plci;
5731 sendf(&application[i],_CONNECT_I,Id,0,
5732 "wSSSSSSSbSSSSS", cip, /* CIP */
5733 parms[0], /* CalledPartyNumber */
5734 multi_CiPN_parms[0], /* CallingPartyNumber */
5735 parms[2], /* CalledPartySubad */
5736 parms[3], /* CallingPartySubad */
5737 parms[4], /* BearerCapability */
5738 parms[5], /* LowLC */
5739 parms[6], /* HighLC */
5740 ai_len, /* nested struct add_i */
5741 add_i[0], /* B channel info */
5742 add_i[1], /* keypad facility */
5743 add_i[2], /* user user data */
5744 add_i[3], /* nested facility */
5745 multi_CiPN_parms[1] /* second CiPN(SCR) */
5747 SendSSExtInd(&application[i],
5748 plci,
5750 multi_ssext_parms);
5751 SendSetupInfo(&application[i],
5752 plci,
5754 parms,
5755 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5758 clear_c_ind_mask_bit (plci, MAX_APPL);
5759 dump_c_ind_mask (plci);
5761 if(c_ind_mask_empty (plci)) {
5762 sig_req(plci,HANGUP,0);
5763 send_req(plci);
5764 plci->State = IDLE;
5766 plci->notifiedcall = 0;
5767 a->listen_active--;
5768 listen_check(a);
5769 break;
5771 case CALL_PEND_NOTIFY:
5772 plci->notifiedcall = 1;
5773 listen_check(a);
5774 break;
5776 case CALL_IND:
5777 case CALL_CON:
5778 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5780 if(plci->internal_command==PERM_COD_CONN_PEND)
5782 if(plci->State==ADVANCED_VOICE_NOSIG)
5784 dbug(1,dprintf("***Codec OK"));
5785 if(a->AdvSignalPLCI)
5787 tplci = a->AdvSignalPLCI;
5788 if(tplci->spoofed_msg)
5790 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5791 tplci->command = 0;
5792 tplci->internal_command = 0;
5793 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5794 switch (tplci->spoofed_msg)
5796 case CALL_RES:
5797 tplci->command = _CONNECT_I|RESPONSE;
5798 api_load_msg (&tplci->saved_msg, saved_parms);
5799 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5800 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5802 /* early B3 connect (CIP mask bit 9) no release after a disc */
5803 add_p(tplci,LLI,"\x01\x01");
5805 add_s(tplci, CONN_NR, &saved_parms[2]);
5806 add_s(tplci, LLC, &saved_parms[4]);
5807 add_ai(tplci, &saved_parms[5]);
5808 tplci->State = INC_CON_ACCEPT;
5809 sig_req(tplci, CALL_RES,0);
5810 send_req(tplci);
5811 break;
5813 case AWAITING_SELECT_B:
5814 dbug(1,dprintf("Select_B continue"));
5815 start_internal_command (x_Id, tplci, select_b_command);
5816 break;
5818 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5819 if(!tplci->Sig.Id)
5821 dbug(1,dprintf("No SigID!"));
5822 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5823 plci_remove(tplci);
5824 break;
5826 tplci->command = _MANUFACTURER_R;
5827 api_load_msg (&tplci->saved_msg, saved_parms);
5828 dir = saved_parms[2].info[0];
5829 if(dir==1) {
5830 sig_req(tplci,CALL_REQ,0);
5832 else if(!dir){
5833 sig_req(tplci,LISTEN_REQ,0);
5835 send_req(tplci);
5836 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5837 break;
5839 case (CALL_REQ|AWAITING_MANUF_CON):
5840 sig_req(tplci,CALL_REQ,0);
5841 send_req(tplci);
5842 break;
5844 case CALL_REQ:
5845 if(!tplci->Sig.Id)
5847 dbug(1,dprintf("No SigID!"));
5848 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5849 plci_remove(tplci);
5850 break;
5852 tplci->command = _CONNECT_R;
5853 api_load_msg (&tplci->saved_msg, saved_parms);
5854 add_s(tplci,CPN,&saved_parms[1]);
5855 add_s(tplci,DSA,&saved_parms[3]);
5856 add_ai(tplci,&saved_parms[9]);
5857 sig_req(tplci,CALL_REQ,0);
5858 send_req(tplci);
5859 break;
5861 case CALL_RETRIEVE:
5862 tplci->command = C_RETRIEVE_REQ;
5863 sig_req(tplci,CALL_RETRIEVE,0);
5864 send_req(tplci);
5865 break;
5867 tplci->spoofed_msg = 0;
5868 if (tplci->internal_command == 0)
5869 next_internal_command (x_Id, tplci);
5872 next_internal_command (Id, plci);
5873 break;
5875 dbug(1,dprintf("***Codec Hook Init Req"));
5876 plci->internal_command = PERM_COD_HOOK;
5877 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5878 sig_req(plci,TEL_CTRL,0);
5879 send_req(plci);
5882 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5883 && plci->State!=INC_ACT_PENDING)
5885 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5886 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5888 chi[2] = plci->b_channel;
5889 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5891 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5892 plci->State = INC_ACT_PENDING;
5894 break;
5896 case TEL_CTRL:
5897 Number = 0;
5898 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5899 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5900 switch (ie[1]&0x91) {
5901 case 0x80: /* hook off */
5902 case 0x81:
5903 if(plci->internal_command==PERM_COD_HOOK)
5905 dbug(1,dprintf("init:hook_off"));
5906 plci->hook_state = ie[1];
5907 next_internal_command (Id, plci);
5908 break;
5910 else /* ignore doubled hook indications */
5912 if( ((plci->hook_state)&0xf0)==0x80)
5914 dbug(1,dprintf("ignore hook"));
5915 break;
5917 plci->hook_state = ie[1]&0x91;
5919 /* check for incoming call pending */
5920 /* and signal '+'.Appl must decide */
5921 /* with connect_res if call must */
5922 /* accepted or not */
5923 for(i=0, tplci=NULL;i<max_appl;i++){
5924 if(a->codec_listen[i]
5925 && (a->codec_listen[i]->State==INC_CON_PENDING
5926 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5927 tplci = a->codec_listen[i];
5928 tplci->appl = &application[i];
5931 /* no incoming call, do outgoing call */
5932 /* and signal '+' if outg. setup */
5933 if(!a->AdvSignalPLCI && !tplci){
5934 if((i=get_plci(a))) {
5935 a->AdvSignalPLCI = &a->plci[i-1];
5936 tplci = a->AdvSignalPLCI;
5937 tplci->tel = ADV_VOICE;
5938 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5939 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5940 /* early B3 connect (CIP mask bit 9) no release after a disc */
5941 add_p(tplci,LLI,"\x01\x01");
5943 add_p(tplci, CAI, voice_cai);
5944 add_p(tplci, OAD, a->TelOAD);
5945 add_p(tplci, OSA, a->TelOSA);
5946 add_p(tplci,SHIFT|6,NULL);
5947 add_p(tplci,SIN,"\x02\x01\x00");
5948 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5949 sig_req(tplci,ASSIGN,DSIG_ID);
5950 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5951 a->AdvSignalPLCI->command = 0;
5952 tplci->appl = a->AdvSignalAppl;
5953 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5954 send_req(tplci);
5959 if(!tplci) break;
5960 Id = ((word)tplci->Id<<8)|a->Id;
5961 Id|=EXT_CONTROLLER;
5962 sendf(tplci->appl,
5963 _FACILITY_I,
5966 "ws", (word)0, "\x01+");
5967 break;
5969 case 0x90: /* hook on */
5970 case 0x91:
5971 if(plci->internal_command==PERM_COD_HOOK)
5973 dbug(1,dprintf("init:hook_on"));
5974 plci->hook_state = ie[1]&0x91;
5975 next_internal_command (Id, plci);
5976 break;
5978 else /* ignore doubled hook indications */
5980 if( ((plci->hook_state)&0xf0)==0x90) break;
5981 plci->hook_state = ie[1]&0x91;
5983 /* hangup the adv. voice call and signal '-' to the appl */
5984 if(a->AdvSignalPLCI) {
5985 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5986 if(plci->tel) Id|=EXT_CONTROLLER;
5987 sendf(a->AdvSignalAppl,
5988 _FACILITY_I,
5991 "ws", (word)0, "\x01-");
5992 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5993 a->AdvSignalPLCI->command = 0;
5994 sig_req(a->AdvSignalPLCI,HANGUP,0);
5995 send_req(a->AdvSignalPLCI);
5997 break;
6000 break;
6002 case RESUME:
6003 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
6004 PUT_WORD(&resume_cau[4],GOOD);
6005 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6006 break;
6008 case SUSPEND:
6009 clear_c_ind_mask (plci);
6011 if (plci->NL.Id && !plci->nl_remove_id) {
6012 mixer_remove (plci);
6013 nl_req_ncci(plci,REMOVE,0);
6015 if (!plci->sig_remove_id) {
6016 plci->internal_command = 0;
6017 sig_req(plci,REMOVE,0);
6019 send_req(plci);
6020 if(!plci->channels) {
6021 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6022 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6024 break;
6026 case SUSPEND_REJ:
6027 break;
6029 case HANGUP:
6030 plci->hangup_flow_ctrl_timer=0;
6031 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6032 cau = parms[7];
6033 if(cau) {
6034 i = _L3_CAUSE | cau[2];
6035 if(cau[2]==0) i = 0;
6036 else if(cau[2]==8) i = _L1_ERROR;
6037 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6038 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6040 else {
6041 i = _L3_ERROR;
6044 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6046 for(i=0; i<max_appl; i++)
6048 if(test_c_ind_mask_bit (plci, i))
6049 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6052 else
6054 clear_c_ind_mask (plci);
6056 if(!plci->appl)
6058 if (plci->State == LISTENING)
6060 plci->notifiedcall=0;
6061 a->listen_active--;
6063 plci->State = INC_DIS_PENDING;
6064 if(c_ind_mask_empty (plci))
6066 plci->State = IDLE;
6067 if (plci->NL.Id && !plci->nl_remove_id)
6069 mixer_remove (plci);
6070 nl_req_ncci(plci,REMOVE,0);
6072 if (!plci->sig_remove_id)
6074 plci->internal_command = 0;
6075 sig_req(plci,REMOVE,0);
6077 send_req(plci);
6080 else
6082 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6083 /* result in a second HANGUP! Don't generate another */
6084 /* DISCONNECT */
6085 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6087 if(plci->State==RESUMING)
6089 PUT_WORD(&resume_cau[4],i);
6090 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6092 plci->State = INC_DIS_PENDING;
6093 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6096 break;
6098 case SSEXT_IND:
6099 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6100 break;
6102 case VSWITCH_REQ:
6103 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6104 break;
6105 case VSWITCH_IND:
6106 if(plci->relatedPTYPLCI &&
6107 plci->vswitchstate==3 &&
6108 plci->relatedPTYPLCI->vswitchstate==3 &&
6109 parms[MAXPARMSIDS-1][0])
6111 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6112 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6113 send_req(plci->relatedPTYPLCI);
6115 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6116 break;
6122 static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6124 word i;
6125 byte * ie;
6126 word Info_Number;
6127 byte * Info_Element;
6128 word Info_Mask = 0;
6130 dbug(1,dprintf("SetupInfo"));
6132 for(i=0; i<MAXPARMSIDS; i++) {
6133 ie = parms[i];
6134 Info_Number = 0;
6135 Info_Element = ie;
6136 if(ie[0]) {
6137 switch(i) {
6138 case 0:
6139 dbug(1,dprintf("CPN "));
6140 Info_Number = 0x0070;
6141 Info_Mask = 0x80;
6142 Info_Sent_Flag = true;
6143 break;
6144 case 8: /* display */
6145 dbug(1,dprintf("display(%d)",i));
6146 Info_Number = 0x0028;
6147 Info_Mask = 0x04;
6148 Info_Sent_Flag = true;
6149 break;
6150 case 16: /* Channel Id */
6151 dbug(1,dprintf("CHI"));
6152 Info_Number = 0x0018;
6153 Info_Mask = 0x100;
6154 Info_Sent_Flag = true;
6155 mixer_set_bchannel_id (plci, Info_Element);
6156 break;
6157 case 19: /* Redirected Number */
6158 dbug(1,dprintf("RDN"));
6159 Info_Number = 0x0074;
6160 Info_Mask = 0x400;
6161 Info_Sent_Flag = true;
6162 break;
6163 case 20: /* Redirected Number extended */
6164 dbug(1,dprintf("RDX"));
6165 Info_Number = 0x0073;
6166 Info_Mask = 0x400;
6167 Info_Sent_Flag = true;
6168 break;
6169 case 22: /* Redirecing Number */
6170 dbug(1,dprintf("RIN"));
6171 Info_Number = 0x0076;
6172 Info_Mask = 0x400;
6173 Info_Sent_Flag = true;
6174 break;
6175 default:
6176 Info_Number = 0;
6177 break;
6181 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6182 Info_Number = 0x8000 |5;
6183 Info_Mask = 0x10;
6184 Info_Element = "";
6187 if(Info_Sent_Flag && Info_Number){
6188 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6189 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6196 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6198 word i;
6199 word j;
6200 word k;
6201 byte * ie;
6202 word Info_Number;
6203 byte * Info_Element;
6204 word Info_Mask = 0;
6205 static byte charges[5] = {4,0,0,0,0};
6206 static byte cause[] = {0x02,0x80,0x00};
6207 APPL *appl;
6209 dbug(1,dprintf("InfoParse "));
6212 !plci->appl
6213 && !plci->State
6214 && plci->Sig.Ind!=NCR_FACILITY
6217 dbug(1,dprintf("NoParse "));
6218 return;
6220 cause[2] = 0;
6221 for(i=0; i<MAXPARMSIDS; i++) {
6222 ie = parms[i];
6223 Info_Number = 0;
6224 Info_Element = ie;
6225 if(ie[0]) {
6226 switch(i) {
6227 case 0:
6228 dbug(1,dprintf("CPN "));
6229 Info_Number = 0x0070;
6230 Info_Mask = 0x80;
6231 break;
6232 case 7: /* ESC_CAU */
6233 dbug(1,dprintf("cau(0x%x)",ie[2]));
6234 Info_Number = 0x0008;
6235 Info_Mask = 0x00;
6236 cause[2] = ie[2];
6237 Info_Element = NULL;
6238 break;
6239 case 8: /* display */
6240 dbug(1,dprintf("display(%d)",i));
6241 Info_Number = 0x0028;
6242 Info_Mask = 0x04;
6243 break;
6244 case 9: /* Date display */
6245 dbug(1,dprintf("date(%d)",i));
6246 Info_Number = 0x0029;
6247 Info_Mask = 0x02;
6248 break;
6249 case 10: /* charges */
6250 for(j=0;j<4;j++) charges[1+j] = 0;
6251 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6252 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6253 Info_Number = 0x4000;
6254 Info_Mask = 0x40;
6255 Info_Element = charges;
6256 break;
6257 case 11: /* user user info */
6258 dbug(1,dprintf("uui"));
6259 Info_Number = 0x007E;
6260 Info_Mask = 0x08;
6261 break;
6262 case 12: /* congestion receiver ready */
6263 dbug(1,dprintf("clRDY"));
6264 Info_Number = 0x00B0;
6265 Info_Mask = 0x08;
6266 Info_Element = "";
6267 break;
6268 case 13: /* congestion receiver not ready */
6269 dbug(1,dprintf("clNRDY"));
6270 Info_Number = 0x00BF;
6271 Info_Mask = 0x08;
6272 Info_Element = "";
6273 break;
6274 case 15: /* Keypad Facility */
6275 dbug(1,dprintf("KEY"));
6276 Info_Number = 0x002C;
6277 Info_Mask = 0x20;
6278 break;
6279 case 16: /* Channel Id */
6280 dbug(1,dprintf("CHI"));
6281 Info_Number = 0x0018;
6282 Info_Mask = 0x100;
6283 mixer_set_bchannel_id (plci, Info_Element);
6284 break;
6285 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6286 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6287 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6288 Info_Number = 0x0008;
6289 Info_Mask = 0x01;
6290 if(cause[2] != ie[2]) Info_Element = cause;
6291 break;
6292 case 19: /* Redirected Number */
6293 dbug(1,dprintf("RDN"));
6294 Info_Number = 0x0074;
6295 Info_Mask = 0x400;
6296 break;
6297 case 22: /* Redirecing Number */
6298 dbug(1,dprintf("RIN"));
6299 Info_Number = 0x0076;
6300 Info_Mask = 0x400;
6301 break;
6302 case 23: /* Notification Indicator */
6303 dbug(1,dprintf("NI"));
6304 Info_Number = (word)NI;
6305 Info_Mask = 0x210;
6306 break;
6307 case 26: /* Call State */
6308 dbug(1,dprintf("CST"));
6309 Info_Number = (word)CST;
6310 Info_Mask = 0x01; /* do with cause i.e. for now */
6311 break;
6312 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6313 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6314 Info_Number = 0x8000 |ie[3];
6315 if(iesent) Info_Mask = 0xffff;
6316 else Info_Mask = 0x10;
6317 Info_Element = "";
6318 break;
6319 default:
6320 Info_Number = 0;
6321 Info_Mask = 0;
6322 Info_Element = "";
6323 break;
6327 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6329 for(j=0; j<max_appl; j++)
6331 appl = &application[j];
6332 if(Info_Number
6333 && appl->Id
6334 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6336 dbug(1,dprintf("NCR_Ind"));
6337 iesent=true;
6338 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6342 else if(!plci->appl)
6343 { /* overlap receiving broadcast */
6344 if(Info_Number==CPN
6345 || Info_Number==KEY
6346 || Info_Number==NI
6347 || Info_Number==DSP
6348 || Info_Number==UUI )
6350 for(j=0; j<max_appl; j++)
6352 if(test_c_ind_mask_bit (plci, j))
6354 dbug(1,dprintf("Ovl_Ind"));
6355 iesent=true;
6356 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6360 } /* all other signalling states */
6361 else if(Info_Number
6362 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6364 dbug(1,dprintf("Std_Ind"));
6365 iesent=true;
6366 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6372 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6373 dword info_mask, byte setupParse)
6375 word i;
6376 word j;
6377 byte * ie;
6378 word Info_Number;
6379 byte * Info_Element;
6380 APPL *appl;
6381 word Info_Mask = 0;
6382 byte iesent=0;
6385 !plci->appl
6386 && !plci->State
6387 && plci->Sig.Ind!=NCR_FACILITY
6388 && !setupParse
6391 dbug(1,dprintf("NoM-IEParse "));
6392 return 0;
6394 dbug(1,dprintf("M-IEParse "));
6396 for(i=0; i<MAX_MULTI_IE; i++)
6398 ie = parms[i];
6399 Info_Number = 0;
6400 Info_Element = ie;
6401 if(ie[0])
6403 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6404 Info_Number = (word)ie_type;
6405 Info_Mask = (word)info_mask;
6408 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6410 for(j=0; j<max_appl; j++)
6412 appl = &application[j];
6413 if(Info_Number
6414 && appl->Id
6415 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6417 iesent = true;
6418 dbug(1,dprintf("Mlt_NCR_Ind"));
6419 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6423 else if(!plci->appl && Info_Number)
6424 { /* overlap receiving broadcast */
6425 for(j=0; j<max_appl; j++)
6427 if(test_c_ind_mask_bit (plci, j))
6429 iesent = true;
6430 dbug(1,dprintf("Mlt_Ovl_Ind"));
6431 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6434 } /* all other signalling states */
6435 else if(Info_Number
6436 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6438 iesent = true;
6439 dbug(1,dprintf("Mlt_Std_Ind"));
6440 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6443 return iesent;
6446 static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6448 word i;
6449 /* Format of multi_ssext_parms[i][]:
6450 0 byte length
6451 1 byte SSEXTIE
6452 2 byte SSEXT_REQ/SSEXT_IND
6453 3 byte length
6454 4 word SSExtCommand
6455 6... Params
6458 plci
6459 && plci->State
6460 && plci->Sig.Ind!=NCR_FACILITY
6462 for(i=0;i<MAX_MULTI_IE;i++)
6464 if(parms[i][0]<6) continue;
6465 if(parms[i][2]==SSEXT_REQ) continue;
6467 if(appl)
6469 parms[i][0]=0; /* kill it */
6470 sendf(appl,_MANUFACTURER_I,
6473 "dwS",
6474 _DI_MANU_ID,
6475 _DI_SSEXT_CTRL,
6476 &parms[i][3]);
6478 else if(plci->appl)
6480 parms[i][0]=0; /* kill it */
6481 sendf(plci->appl,_MANUFACTURER_I,
6484 "dwS",
6485 _DI_MANU_ID,
6486 _DI_SSEXT_CTRL,
6487 &parms[i][3]);
6492 static void nl_ind(PLCI *plci)
6494 byte ch;
6495 word ncci;
6496 dword Id;
6497 DIVA_CAPI_ADAPTER * a;
6498 word NCCIcode;
6499 APPL * APPLptr;
6500 word count;
6501 word Num;
6502 word i, ncpi_state;
6503 byte len, ncci_state;
6504 word msg;
6505 word info = 0;
6506 word fax_feature_bits;
6507 byte fax_send_edata_ack;
6508 static byte v120_header_buffer[2 + 3];
6509 static word fax_info[] = {
6510 0, /* T30_SUCCESS */
6511 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6516 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6517 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6518 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6519 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6520 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6521 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6522 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6523 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6524 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6525 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6526 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6527 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6529 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6531 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6533 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6537 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6538 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6539 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6540 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6541 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6542 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6543 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6544 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6545 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6546 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6547 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6548 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6549 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6550 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6551 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6552 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6553 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6554 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6555 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6556 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6559 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6562 static word rtp_info[] = {
6563 GOOD, /* RTP_SUCCESS */
6564 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6567 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6569 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6570 0x00000000, 0x00000000, 0x00000000, 0x00000000
6573 ch = plci->NL.IndCh;
6574 a = plci->adapter;
6575 ncci = a->ch_ncci[ch];
6576 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6577 if(plci->tel) Id|=EXT_CONTROLLER;
6578 APPLptr = plci->appl;
6579 dbug(1,dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6580 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6582 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6584 if (plci->nl_remove_id)
6586 plci->NL.RNR = 2; /* discard */
6587 dbug(1,dprintf("NL discard while remove pending"));
6588 return;
6590 if((plci->NL.Ind &0x0f)==N_CONNECT)
6592 if(plci->State==INC_DIS_PENDING
6593 || plci->State==OUTG_DIS_PENDING
6594 || plci->State==IDLE)
6596 plci->NL.RNR = 2; /* discard */
6597 dbug(1,dprintf("discard n_connect"));
6598 return;
6600 if(plci->State < INC_ACT_PENDING)
6602 plci->NL.RNR = 1; /* flow control */
6603 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6604 return;
6608 if(!APPLptr) /* no application or invalid data */
6609 { /* while reloading the DSP */
6610 dbug(1,dprintf("discard1"));
6611 plci->NL.RNR = 2;
6612 return;
6615 if (((plci->NL.Ind &0x0f) == N_UDATA)
6616 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6617 || (plci->B2_prot == 7)
6618 || (plci->B3_prot == 7)) )
6620 plci->ncpi_buffer[0] = 0;
6622 ncpi_state = plci->ncpi_state;
6623 if (plci->NL.complete == 1)
6625 byte * data = &plci->NL.RBuffer->P[0];
6627 if ((plci->NL.RBuffer->length >= 12)
6628 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6629 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6631 word conn_opt, ncpi_opt = 0x00;
6632 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6634 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6635 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6636 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6637 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6639 data++; /* indication code */
6640 data += 2; /* timestamp */
6641 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6642 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6643 data++; /* connected norm */
6644 conn_opt = GET_WORD(data);
6645 data += 2; /* connected options */
6647 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6649 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6651 ncpi_opt |= MDM_NCPI_ECM_V42;
6653 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6655 ncpi_opt |= MDM_NCPI_ECM_MNP;
6657 else
6659 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6661 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6663 ncpi_opt |= MDM_NCPI_COMPRESSED;
6665 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6666 plci->ncpi_buffer[0] = 4;
6668 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6671 if (plci->B3_prot == 7)
6673 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6674 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6675 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6677 a->ncci_state[ncci] = INC_ACT_PENDING;
6678 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6679 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6683 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6684 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6685 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6686 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6689 plci->NL.RNR = 2;
6690 return;
6694 if(plci->NL.complete == 2)
6696 if (((plci->NL.Ind &0x0f) == N_UDATA)
6697 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6699 switch(plci->RData[0].P[0])
6702 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6703 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6705 break;
6706 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6707 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6708 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6709 break;
6710 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6711 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6712 break;
6713 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6714 dtmf_confirmation (Id, plci);
6715 break;
6718 case UDATA_INDICATION_MIXER_TAP_DATA:
6719 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6720 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6721 if (i != 0)
6723 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6724 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6726 break;
6729 case UDATA_INDICATION_MIXER_COEFS_SET:
6730 mixer_indication_coefs_set (Id, plci);
6731 break;
6732 case UDATA_INDICATION_XCONNECT_FROM:
6733 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6734 break;
6735 case UDATA_INDICATION_XCONNECT_TO:
6736 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6737 break;
6740 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6741 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6742 break;
6746 default:
6747 break;
6750 else
6752 if ((plci->RData[0].PLength != 0)
6753 && ((plci->B2_prot == B2_V120_ASYNC)
6754 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6755 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6758 sendf(plci->appl,_DATA_B3_I,Id,0,
6759 "dwww",
6760 plci->RData[1].P,
6761 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6762 plci->RNum,
6763 plci->RFlags);
6766 else
6769 sendf(plci->appl,_DATA_B3_I,Id,0,
6770 "dwww",
6771 plci->RData[0].P,
6772 plci->RData[0].PLength,
6773 plci->RNum,
6774 plci->RFlags);
6778 return;
6781 fax_feature_bits = 0;
6782 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6783 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6784 (plci->NL.Ind &0x0f)==N_DISC ||
6785 (plci->NL.Ind &0x0f)==N_EDATA ||
6786 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6788 info = 0;
6789 plci->ncpi_buffer[0] = 0;
6790 switch (plci->B3_prot) {
6791 case 0: /*XPARENT*/
6792 case 1: /*T.90 NL*/
6793 break; /* no network control protocol info - jfr */
6794 case 2: /*ISO8202*/
6795 case 3: /*X25 DCE*/
6796 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6797 plci->ncpi_buffer[0] = (byte)(i+3);
6798 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6799 plci->ncpi_buffer[2] = 0;
6800 plci->ncpi_buffer[3] = 0;
6801 break;
6802 case 4: /*T.30 - FAX*/
6803 case 5: /*T.30 - FAX*/
6804 if(plci->NL.RLength>=sizeof(T30_INFO))
6806 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6807 len = 9;
6808 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6809 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6810 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6811 if (plci->B3_prot == 5)
6813 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6814 i |= 0x8000; /* This is not an ECM connection */
6815 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6816 i |= 0x4000; /* This is a connection with MMR compression */
6817 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6818 i |= 0x2000; /* This is a connection with MR compression */
6819 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6820 i |= 0x0004; /* More documents */
6821 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6822 i |= 0x0002; /* Fax-polling indication */
6824 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6825 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6826 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6827 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6828 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6829 plci->ncpi_buffer[len] = 0;
6830 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6832 plci->ncpi_buffer[len] = 20;
6833 for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6834 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6836 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6838 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6839 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6840 else
6841 info = _FAX_PROTOCOL_ERROR;
6844 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6845 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6847 i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6848 while (i < plci->NL.RBuffer->length)
6849 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6852 plci->ncpi_buffer[0] = len;
6853 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6854 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6856 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6857 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6858 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6859 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6860 || (((plci->NL.Ind &0x0f) == N_EDATA)
6861 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6862 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6863 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6865 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6867 if (((plci->NL.Ind &0x0f) == N_DISC)
6868 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6869 || (((plci->NL.Ind &0x0f) == N_EDATA)
6870 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6872 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6875 break;
6877 case B3_RTP:
6878 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6880 if (plci->NL.RLength != 0)
6882 info = rtp_info[plci->NL.RBuffer->P[0]];
6883 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6884 for (i = 1; i < plci->NL.RLength; i++)
6885 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6888 break;
6891 plci->NL.RNR = 2;
6893 switch(plci->NL.Ind &0x0f) {
6894 case N_EDATA:
6895 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6897 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6898 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6899 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6901 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6902 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6903 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6904 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6905 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6906 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6908 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6909 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6910 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6911 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6912 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6913 fax_send_edata_ack = false;
6916 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6918 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6920 case EDATA_T30_DIS:
6921 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6922 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6923 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6924 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6926 a->ncci_state[ncci] = INC_ACT_PENDING;
6927 if (plci->B3_prot == 4)
6928 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6929 else
6930 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6931 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6933 break;
6935 case EDATA_T30_TRAIN_OK:
6936 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6937 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6938 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6940 if (plci->B3_prot == 4)
6941 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6942 else
6943 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6944 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6946 break;
6948 case EDATA_T30_EOP_CAPI:
6949 if (a->ncci_state[ncci] == CONNECTED)
6951 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6952 a->ncci_state[ncci] = INC_DIS_PENDING;
6953 plci->ncpi_state = 0;
6954 fax_send_edata_ack = false;
6956 break;
6959 else
6961 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6963 case EDATA_T30_TRAIN_OK:
6964 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6965 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6966 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6968 if (plci->B3_prot == 4)
6969 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6970 else
6971 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6972 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6974 break;
6977 if (fax_send_edata_ack)
6979 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6980 plci->fax_edata_ack_length = 1;
6981 start_internal_command (Id, plci, fax_edata_ack_command);
6984 else
6986 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6988 break;
6989 case N_CONNECT:
6990 if (!a->ch_ncci[ch])
6992 ncci = get_ncci (plci, ch, 0);
6993 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6995 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6996 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6998 msg = _CONNECT_B3_I;
6999 if (a->ncci_state[ncci] == IDLE)
7000 plci->channels++;
7001 else if (plci->B3_prot == 1)
7002 msg = _CONNECT_B3_T90_ACTIVE_I;
7004 a->ncci_state[ncci] = INC_CON_PENDING;
7005 if(plci->B3_prot == 4)
7006 sendf(plci->appl,msg,Id,0,"s","");
7007 else
7008 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7009 break;
7010 case N_CONNECT_ACK:
7011 dbug(1,dprintf("N_connect_Ack"));
7012 if (plci->internal_command_queue[0]
7013 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7014 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7015 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7017 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7018 if (!plci->internal_command)
7019 next_internal_command (Id, plci);
7020 break;
7022 msg = _CONNECT_B3_ACTIVE_I;
7023 if (plci->B3_prot == 1)
7025 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7026 msg = _CONNECT_B3_T90_ACTIVE_I;
7027 a->ncci_state[ncci] = INC_ACT_PENDING;
7028 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7030 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7032 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7033 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7034 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7036 a->ncci_state[ncci] = INC_ACT_PENDING;
7037 if (plci->B3_prot == 4)
7038 sendf(plci->appl,msg,Id,0,"s","");
7039 else
7040 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7041 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7044 else
7046 a->ncci_state[ncci] = INC_ACT_PENDING;
7047 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7049 if (plci->adjust_b_restore)
7051 plci->adjust_b_restore = false;
7052 start_internal_command (Id, plci, adjust_b_restore);
7054 break;
7055 case N_DISC:
7056 case N_DISC_ACK:
7057 if (plci->internal_command_queue[0]
7058 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7059 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7060 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7062 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7063 if (!plci->internal_command)
7064 next_internal_command (Id, plci);
7066 ncci_state = a->ncci_state[ncci];
7067 ncci_remove (plci, ncci, false);
7069 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7070 /* channel, so we cannot store the state in ncci_state! The */
7071 /* information which channel we received a N_DISC is thus */
7072 /* stored in the inc_dis_ncci_table buffer. */
7073 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7074 plci->inc_dis_ncci_table[i] = (byte) ncci;
7076 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7077 if (!plci->channels
7078 && (plci->B1_resource == 16)
7079 && (plci->State <= CONNECTED))
7081 len = 9;
7082 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7083 PUT_WORD (&plci->ncpi_buffer[1], i);
7084 PUT_WORD (&plci->ncpi_buffer[3], 0);
7085 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7086 PUT_WORD (&plci->ncpi_buffer[5], i);
7087 PUT_WORD (&plci->ncpi_buffer[7], 0);
7088 plci->ncpi_buffer[len] = 0;
7089 plci->ncpi_buffer[0] = len;
7090 if(plci->B3_prot == 4)
7091 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7092 else
7095 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7096 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7098 plci->ncpi_buffer[++len] = 0;
7099 plci->ncpi_buffer[++len] = 0;
7100 plci->ncpi_buffer[++len] = 0;
7101 plci->ncpi_buffer[0] = len;
7104 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7106 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7107 plci->ncpi_state = 0;
7108 sig_req(plci,HANGUP,0);
7109 send_req(plci);
7110 plci->State = OUTG_DIS_PENDING;
7111 /* disc here */
7113 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7114 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7115 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7117 if (ncci_state == IDLE)
7119 if (plci->channels)
7120 plci->channels--;
7121 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7122 if(plci->State == SUSPENDING){
7123 sendf(plci->appl,
7124 _FACILITY_I,
7125 Id & 0xffffL,
7127 "ws", (word)3, "\x03\x04\x00\x00");
7128 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7130 plci_remove(plci);
7131 plci->State=IDLE;
7135 else if (plci->channels)
7137 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7138 plci->ncpi_state = 0;
7139 if ((ncci_state == OUTG_REJ_PENDING)
7140 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7142 sig_req(plci,HANGUP,0);
7143 send_req(plci);
7144 plci->State = OUTG_DIS_PENDING;
7147 break;
7148 case N_RESET:
7149 a->ncci_state[ncci] = INC_RES_PENDING;
7150 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7151 break;
7152 case N_RESET_ACK:
7153 a->ncci_state[ncci] = CONNECTED;
7154 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7155 break;
7157 case N_UDATA:
7158 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7160 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7161 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7162 plci->NL.R = plci->RData;
7163 plci->NL.RNum = 1;
7164 return;
7166 case N_BDATA:
7167 case N_DATA:
7168 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7169 || (a->ncci_state[ncci] == IDLE)
7170 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7172 plci->NL.RNR = 2;
7173 break;
7175 if ((a->ncci_state[ncci] != CONNECTED)
7176 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7177 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7179 dbug(1,dprintf("flow control"));
7180 plci->NL.RNR = 1; /* flow control */
7181 channel_x_off (plci, ch, 0);
7182 break;
7185 NCCIcode = ncci | (((word)a->Id) << 8);
7187 /* count all buffers within the Application pool */
7188 /* belonging to the same NCCI. If this is below the */
7189 /* number of buffers available per NCCI we accept */
7190 /* this packet, otherwise we reject it */
7191 count = 0;
7192 Num = 0xffff;
7193 for(i=0; i<APPLptr->MaxBuffer; i++) {
7194 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7195 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7198 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7200 dbug(3,dprintf("Flow-Control"));
7201 plci->NL.RNR = 1;
7202 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7203 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7205 plci->NL.RNR = 2;
7206 dbug(3,dprintf("DiscardData"));
7207 } else {
7208 channel_x_off (plci, ch, 0);
7210 break;
7212 else
7214 APPLptr->NCCIDataFlowCtrlTimer = 0;
7217 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7218 if(!plci->RData[0].P) {
7219 plci->NL.RNR = 1;
7220 channel_x_off (plci, ch, 0);
7221 break;
7224 APPLptr->DataNCCI[Num] = NCCIcode;
7225 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7226 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7228 plci->RNum = Num;
7229 plci->RFlags = plci->NL.Ind>>4;
7230 plci->RData[0].PLength = APPLptr->MaxDataLength;
7231 plci->NL.R = plci->RData;
7232 if ((plci->NL.RLength != 0)
7233 && ((plci->B2_prot == B2_V120_ASYNC)
7234 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7235 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7237 plci->RData[1].P = plci->RData[0].P;
7238 plci->RData[1].PLength = plci->RData[0].PLength;
7239 plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7240 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7241 plci->RData[0].PLength = 1;
7242 else
7243 plci->RData[0].PLength = 2;
7244 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7245 plci->RFlags |= 0x0010;
7246 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7247 plci->RFlags |= 0x8000;
7248 plci->NL.RNum = 2;
7250 else
7252 if((plci->NL.Ind &0x0f)==N_UDATA)
7253 plci->RFlags |= 0x0010;
7255 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7256 plci->RFlags |= 0x0001;
7258 plci->NL.RNum = 1;
7260 break;
7261 case N_DATA_ACK:
7262 data_ack (plci, ch);
7263 break;
7264 default:
7265 plci->NL.RNR = 2;
7266 break;
7270 /*------------------------------------------------------------------*/
7271 /* find a free PLCI */
7272 /*------------------------------------------------------------------*/
7274 static word get_plci(DIVA_CAPI_ADAPTER *a)
7276 word i,j;
7277 PLCI * plci;
7279 dump_plcis (a);
7280 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7281 if(i==a->max_plci) {
7282 dbug(1,dprintf("get_plci: out of PLCIs"));
7283 return 0;
7285 plci = &a->plci[i];
7286 plci->Id = (byte)(i+1);
7288 plci->Sig.Id = 0;
7289 plci->NL.Id = 0;
7290 plci->sig_req = 0;
7291 plci->nl_req = 0;
7293 plci->appl = NULL;
7294 plci->relatedPTYPLCI = NULL;
7295 plci->State = IDLE;
7296 plci->SuppState = IDLE;
7297 plci->channels = 0;
7298 plci->tel = 0;
7299 plci->B1_resource = 0;
7300 plci->B2_prot = 0;
7301 plci->B3_prot = 0;
7303 plci->command = 0;
7304 plci->m_command = 0;
7305 init_internal_command_queue (plci);
7306 plci->number = 0;
7307 plci->req_in_start = 0;
7308 plci->req_in = 0;
7309 plci->req_out = 0;
7310 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7311 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7312 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7314 plci->data_sent = false;
7315 plci->send_disc = 0;
7316 plci->sig_global_req = 0;
7317 plci->sig_remove_id = 0;
7318 plci->nl_global_req = 0;
7319 plci->nl_remove_id = 0;
7320 plci->adv_nl = 0;
7321 plci->manufacturer = false;
7322 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7323 plci->spoofed_msg = 0;
7324 plci->ptyState = 0;
7325 plci->cr_enquiry = false;
7326 plci->hangup_flow_ctrl_timer = 0;
7328 plci->ncci_ring_list = 0;
7329 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7330 clear_c_ind_mask (plci);
7331 set_group_ind_mask (plci);
7332 plci->fax_connect_info_length = 0;
7333 plci->nsf_control_bits = 0;
7334 plci->ncpi_state = 0x00;
7335 plci->ncpi_buffer[0] = 0;
7337 plci->requested_options_conn = 0;
7338 plci->requested_options = 0;
7339 plci->notifiedcall = 0;
7340 plci->vswitchstate = 0;
7341 plci->vsprot = 0;
7342 plci->vsprotdialect = 0;
7343 init_b1_config (plci);
7344 dbug(1,dprintf("get_plci(%x)",plci->Id));
7345 return i+1;
7348 /*------------------------------------------------------------------*/
7349 /* put a parameter in the parameter buffer */
7350 /*------------------------------------------------------------------*/
7352 static void add_p(PLCI * plci, byte code, byte * p)
7354 word p_length;
7356 p_length = 0;
7357 if(p) p_length = p[0];
7358 add_ie(plci, code, p, p_length);
7361 /*------------------------------------------------------------------*/
7362 /* put a structure in the parameter buffer */
7363 /*------------------------------------------------------------------*/
7364 static void add_s(PLCI * plci, byte code, API_PARSE * p)
7366 if(p) add_ie(plci, code, p->info, (word)p->length);
7369 /*------------------------------------------------------------------*/
7370 /* put multiple structures in the parameter buffer */
7371 /*------------------------------------------------------------------*/
7372 static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7374 byte i;
7376 if(p){
7377 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7378 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7379 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7380 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7385 /*------------------------------------------------------------------*/
7386 /* return the channel number sent by the application in a esc_chi */
7387 /*------------------------------------------------------------------*/
7388 static byte getChannel(API_PARSE * p)
7390 byte i;
7392 if(p){
7393 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7394 if(p->info[i]==2){
7395 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7399 return 0;
7403 /*------------------------------------------------------------------*/
7404 /* put an information element in the parameter buffer */
7405 /*------------------------------------------------------------------*/
7407 static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7409 word i;
7411 if(!(code &0x80) && !p_length) return;
7413 if(plci->req_in==plci->req_in_start) {
7414 plci->req_in +=2;
7416 else {
7417 plci->req_in--;
7419 plci->RBuffer[plci->req_in++] = code;
7421 if(p) {
7422 plci->RBuffer[plci->req_in++] = (byte)p_length;
7423 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7426 plci->RBuffer[plci->req_in++] = 0;
7429 /*------------------------------------------------------------------*/
7430 /* put a unstructured data into the buffer */
7431 /*------------------------------------------------------------------*/
7433 static void add_d(PLCI *plci, word length, byte *p)
7435 word i;
7437 if(plci->req_in==plci->req_in_start) {
7438 plci->req_in +=2;
7440 else {
7441 plci->req_in--;
7443 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7446 /*------------------------------------------------------------------*/
7447 /* put parameters from the Additional Info parameter in the */
7448 /* parameter buffer */
7449 /*------------------------------------------------------------------*/
7451 static void add_ai(PLCI *plci, API_PARSE *ai)
7453 word i;
7454 API_PARSE ai_parms[5];
7456 for(i=0;i<5;i++) ai_parms[i].length = 0;
7458 if(!ai->length)
7459 return;
7460 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7461 return;
7463 add_s (plci,KEY,&ai_parms[1]);
7464 add_s (plci,UUI,&ai_parms[2]);
7465 add_ss(plci,FTY,&ai_parms[3]);
7468 /*------------------------------------------------------------------*/
7469 /* put parameter for b1 protocol in the parameter buffer */
7470 /*------------------------------------------------------------------*/
7472 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7473 word b1_facilities)
7475 API_PARSE bp_parms[8];
7476 API_PARSE mdm_cfg[9];
7477 API_PARSE global_config[2];
7478 byte cai[256];
7479 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7480 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7481 word i;
7483 API_PARSE mdm_cfg_v18[4];
7484 word j, n, w;
7485 dword d;
7488 for(i=0;i<8;i++) bp_parms[i].length = 0;
7489 for(i=0;i<2;i++) global_config[i].length = 0;
7491 dbug(1,dprintf("add_b1"));
7492 api_save_msg(bp, "s", &plci->B_protocol);
7494 if(b_channel_info==2){
7495 plci->B1_resource = 0;
7496 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7497 add_p(plci, CAI, "\x01\x00");
7498 dbug(1,dprintf("Cai=1,0 (no resource)"));
7499 return 0;
7502 if(plci->tel == CODEC_PERMANENT) return 0;
7503 else if(plci->tel == CODEC){
7504 plci->B1_resource = 1;
7505 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7506 add_p(plci, CAI, "\x01\x01");
7507 dbug(1,dprintf("Cai=1,1 (Codec)"));
7508 return 0;
7510 else if(plci->tel == ADV_VOICE){
7511 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7512 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7513 voice_cai[1] = plci->B1_resource;
7514 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7515 add_p(plci, CAI, voice_cai);
7516 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7517 return 0;
7519 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7520 if (plci->call_dir & CALL_DIR_OUT)
7521 plci->call_dir |= CALL_DIR_ORIGINATE;
7522 else if (plci->call_dir & CALL_DIR_IN)
7523 plci->call_dir |= CALL_DIR_ANSWER;
7525 if(!bp->length){
7526 plci->B1_resource = 0x5;
7527 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7528 add_p(plci, CAI, "\x01\x05");
7529 return 0;
7532 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7533 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7534 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7536 bp_parms[6].length = 0;
7537 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7539 dbug(1,dprintf("b-form.!"));
7540 return _WRONG_MESSAGE_FORMAT;
7543 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7545 dbug(1,dprintf("b-form.!"));
7546 return _WRONG_MESSAGE_FORMAT;
7549 if(bp_parms[6].length)
7551 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7553 return _WRONG_MESSAGE_FORMAT;
7555 switch(GET_WORD(global_config[0].info))
7557 case 1:
7558 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7559 break;
7560 case 2:
7561 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7562 break;
7565 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7568 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7569 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7571 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7572 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7573 cai[1] = plci->B1_resource;
7574 cai[2] = 0;
7575 cai[3] = 0;
7576 cai[4] = 0;
7577 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7578 for (i = 0; i < bp_parms[3].length; i++)
7579 cai[7+i] = bp_parms[3].info[1+i];
7580 cai[0] = 6 + bp_parms[3].length;
7581 add_p(plci, CAI, cai);
7582 return 0;
7586 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7587 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7589 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7590 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7591 cai[1] = plci->B1_resource;
7592 cai[2] = 0;
7593 cai[3] = 0;
7594 cai[4] = 0;
7595 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7596 cai[0] = 6;
7597 add_p(plci, CAI, cai);
7598 return 0;
7602 if ((GET_WORD(bp_parms[0].info) >= 32)
7603 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7604 && ((GET_WORD(bp_parms[0].info) != 3)
7605 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7606 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7608 return _B1_NOT_SUPPORTED;
7610 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7611 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7612 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7613 cai[0] = 6;
7614 cai[1] = plci->B1_resource;
7615 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7617 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7618 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7619 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7620 { /* B1 - modem */
7621 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7623 if (bp_parms[3].length)
7625 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7627 return (_WRONG_MESSAGE_FORMAT);
7630 cai[2] = 0; /* Bit rate for adaptation */
7632 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7634 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7635 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7636 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7637 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7639 cai[3] = 0; /* Async framing parameters */
7640 switch (GET_WORD (mdm_cfg[2].info))
7641 { /* Parity */
7642 case 1: /* odd parity */
7643 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7644 dbug(1,dprintf("MDM: odd parity"));
7645 break;
7647 case 2: /* even parity */
7648 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7649 dbug(1,dprintf("MDM: even parity"));
7650 break;
7652 default:
7653 dbug(1,dprintf("MDM: no parity"));
7654 break;
7657 switch (GET_WORD (mdm_cfg[3].info))
7658 { /* stop bits */
7659 case 1: /* 2 stop bits */
7660 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7661 dbug(1,dprintf("MDM: 2 stop bits"));
7662 break;
7664 default:
7665 dbug(1,dprintf("MDM: 1 stop bit"));
7666 break;
7669 switch (GET_WORD (mdm_cfg[1].info))
7670 { /* char length */
7671 case 5:
7672 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7673 dbug(1,dprintf("MDM: 5 bits"));
7674 break;
7676 case 6:
7677 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7678 dbug(1,dprintf("MDM: 6 bits"));
7679 break;
7681 case 7:
7682 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7683 dbug(1,dprintf("MDM: 7 bits"));
7684 break;
7686 default:
7687 dbug(1,dprintf("MDM: 8 bits"));
7688 break;
7691 cai[7] = 0; /* Line taking options */
7692 cai[8] = 0; /* Modulation negotiation options */
7693 cai[9] = 0; /* Modulation options */
7695 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7697 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7698 dbug(1, dprintf("MDM: Reverse direction"));
7701 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7703 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7704 dbug(1, dprintf("MDM: Disable retrain"));
7707 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7709 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7710 dbug(1, dprintf("MDM: Disable ring tone"));
7713 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7715 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7716 dbug(1, dprintf("MDM: 1800 guard tone"));
7718 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7720 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7721 dbug(1, dprintf("MDM: 550 guard tone"));
7724 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7726 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7727 dbug(1, dprintf("MDM: V100"));
7729 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7731 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7732 dbug(1, dprintf("MDM: IN CLASS"));
7734 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7736 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7737 dbug(1, dprintf("MDM: DISABLED"));
7739 cai[0] = 20;
7741 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7742 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7744 plci->requested_options |= 1L << PRIVATE_V18;
7746 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7747 plci->requested_options |= 1L << PRIVATE_VOWN;
7749 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7750 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7752 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7754 i = 27;
7755 if (mdm_cfg[6].length >= 4)
7757 d = GET_DWORD(&mdm_cfg[6].info[1]);
7758 cai[7] |= (byte) d; /* line taking options */
7759 cai[9] |= (byte)(d >> 8); /* modulation options */
7760 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7761 cai[++i] = (byte)(d >> 24);
7762 if (mdm_cfg[6].length >= 8)
7764 d = GET_DWORD(&mdm_cfg[6].info[5]);
7765 cai[10] |= (byte) d; /* disabled modulations mask */
7766 cai[11] |= (byte)(d >> 8);
7767 if (mdm_cfg[6].length >= 12)
7769 d = GET_DWORD(&mdm_cfg[6].info[9]);
7770 cai[12] = (byte) d; /* enabled modulations mask */
7771 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7772 cai[++i] = (byte)(d >> 16);
7773 cai[++i] = (byte)(d >> 24);
7774 cai[++i] = 0;
7775 if (mdm_cfg[6].length >= 14)
7777 w = GET_WORD(&mdm_cfg[6].info[13]);
7778 if (w != 0)
7779 PUT_WORD(&cai[13], w); /* min tx speed */
7780 if (mdm_cfg[6].length >= 16)
7782 w = GET_WORD(&mdm_cfg[6].info[15]);
7783 if (w != 0)
7784 PUT_WORD(&cai[15], w); /* max tx speed */
7785 if (mdm_cfg[6].length >= 18)
7787 w = GET_WORD(&mdm_cfg[6].info[17]);
7788 if (w != 0)
7789 PUT_WORD(&cai[17], w); /* min rx speed */
7790 if (mdm_cfg[6].length >= 20)
7792 w = GET_WORD(&mdm_cfg[6].info[19]);
7793 if (w != 0)
7794 PUT_WORD(&cai[19], w); /* max rx speed */
7795 if (mdm_cfg[6].length >= 22)
7797 w = GET_WORD(&mdm_cfg[6].info[21]);
7798 cai[23] = (byte)(-((short) w)); /* transmit level */
7799 if (mdm_cfg[6].length >= 24)
7801 w = GET_WORD(&mdm_cfg[6].info[23]);
7802 cai[22] |= (byte) w; /* info options mask */
7803 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7813 cai[27] = i - 27;
7814 i++;
7815 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7817 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7819 for (n = 0; n < 3; n++)
7821 cai[i] = (byte)(mdm_cfg_v18[n].length);
7822 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7823 cai[i+j] = mdm_cfg_v18[n].info[j];
7824 i += cai[i] + 1;
7828 cai[0] = (byte)(i - 1);
7834 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7835 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7837 if(bp_parms[3].length){
7838 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7839 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7840 case 0:
7841 case 56000:
7842 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7843 dbug(1,dprintf("56k sync HSCX"));
7844 cai[1] = 8;
7845 cai[2] = 0;
7846 cai[3] = 0;
7848 else if(GET_WORD(bp_parms[0].info)==2){
7849 dbug(1,dprintf("56k async DSP"));
7850 cai[2] = 9;
7852 break;
7853 case 50: cai[2] = 1; break;
7854 case 75: cai[2] = 1; break;
7855 case 110: cai[2] = 1; break;
7856 case 150: cai[2] = 1; break;
7857 case 200: cai[2] = 1; break;
7858 case 300: cai[2] = 1; break;
7859 case 600: cai[2] = 1; break;
7860 case 1200: cai[2] = 2; break;
7861 case 2400: cai[2] = 3; break;
7862 case 4800: cai[2] = 4; break;
7863 case 7200: cai[2] = 10; break;
7864 case 9600: cai[2] = 5; break;
7865 case 12000: cai[2] = 13; break;
7866 case 24000: cai[2] = 0; break;
7867 case 14400: cai[2] = 11; break;
7868 case 19200: cai[2] = 6; break;
7869 case 28800: cai[2] = 12; break;
7870 case 38400: cai[2] = 7; break;
7871 case 48000: cai[2] = 8; break;
7872 case 76: cai[2] = 15; break; /* 75/1200 */
7873 case 1201: cai[2] = 14; break; /* 1200/75 */
7874 case 56001: cai[2] = 9; break; /* V.110 56000 */
7876 default:
7877 return _B1_PARM_NOT_SUPPORTED;
7879 cai[3] = 0;
7880 if (cai[1] == 13) /* v.110 async */
7882 if (bp_parms[3].length >= 8)
7884 switch (GET_WORD (&bp_parms[3].info[3]))
7885 { /* char length */
7886 case 5:
7887 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7888 break;
7889 case 6:
7890 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7891 break;
7892 case 7:
7893 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7894 break;
7896 switch (GET_WORD (&bp_parms[3].info[5]))
7897 { /* Parity */
7898 case 1: /* odd parity */
7899 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7900 break;
7901 case 2: /* even parity */
7902 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7903 break;
7905 switch (GET_WORD (&bp_parms[3].info[7]))
7906 { /* stop bits */
7907 case 1: /* 2 stop bits */
7908 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7909 break;
7914 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7915 dbug(1,dprintf("V.110 default 56k sync"));
7916 cai[1] = 8;
7917 cai[2] = 0;
7918 cai[3] = 0;
7920 else {
7921 dbug(1,dprintf("V.110 default 9600 async"));
7922 cai[2] = 5;
7925 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7926 dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7927 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7929 add_p(plci, CAI, cai);
7930 return 0;
7933 /*------------------------------------------------------------------*/
7934 /* put parameter for b2 and B3 protocol in the parameter buffer */
7935 /*------------------------------------------------------------------*/
7937 static word add_b23(PLCI *plci, API_PARSE *bp)
7939 word i, fax_control_bits;
7940 byte pos, len;
7941 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7942 API_PARSE bp_parms[8];
7943 API_PARSE * b1_config;
7944 API_PARSE * b2_config;
7945 API_PARSE b2_config_parms[8];
7946 API_PARSE * b3_config;
7947 API_PARSE b3_config_parms[6];
7948 API_PARSE global_config[2];
7950 static byte llc[3] = {2,0,0};
7951 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7952 static byte nlc[256];
7953 static byte lli[12] = {1,1};
7955 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7956 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7958 const byte llc3[] = {4,3,2,2,6,6,0};
7959 const byte header[] = {0,2,3,3,0,0,0};
7961 for(i=0;i<8;i++) bp_parms[i].length = 0;
7962 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7963 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7965 lli[0] = 1;
7966 lli[1] = 1;
7967 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7968 lli[1] |= 2;
7969 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7970 lli[1] |= 4;
7972 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7973 lli[1] |= 0x10;
7974 if (plci->rx_dma_descriptor <= 0) {
7975 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7976 if (plci->rx_dma_descriptor >= 0)
7977 plci->rx_dma_descriptor++;
7979 if (plci->rx_dma_descriptor > 0) {
7980 lli[0] = 6;
7981 lli[1] |= 0x40;
7982 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7983 lli[3] = (byte)plci->rx_dma_magic;
7984 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7985 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7986 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7990 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7991 lli[1] |= 0x20;
7994 dbug(1,dprintf("add_b23"));
7995 api_save_msg(bp, "s", &plci->B_protocol);
7997 if(!bp->length && plci->tel)
7999 plci->adv_nl = true;
8000 dbug(1,dprintf("Default adv.Nl"));
8001 add_p(plci,LLI,lli);
8002 plci->B2_prot = 1 /*XPARENT*/;
8003 plci->B3_prot = 0 /*XPARENT*/;
8004 llc[1] = 2;
8005 llc[2] = 4;
8006 add_p(plci, LLC, llc);
8007 dlc[0] = 2;
8008 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8009 add_p(plci, DLC, dlc);
8010 return 0;
8013 if(!bp->length) /*default*/
8015 dbug(1,dprintf("ret default"));
8016 add_p(plci,LLI,lli);
8017 plci->B2_prot = 0 /*X.75 */;
8018 plci->B3_prot = 0 /*XPARENT*/;
8019 llc[1] = 1;
8020 llc[2] = 4;
8021 add_p(plci, LLC, llc);
8022 dlc[0] = 2;
8023 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8024 add_p(plci, DLC, dlc);
8025 return 0;
8027 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8028 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8030 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8032 bp_parms[6].length = 0;
8033 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8035 dbug(1,dprintf("b-form.!"));
8036 return _WRONG_MESSAGE_FORMAT;
8039 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8041 dbug(1,dprintf("b-form.!"));
8042 return _WRONG_MESSAGE_FORMAT;
8045 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8047 if(GET_WORD(bp_parms[1].info)!=1
8048 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8049 plci->adv_nl = true;
8051 else if(plci->tel) return _B2_NOT_SUPPORTED;
8054 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8055 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8056 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8058 add_p(plci,LLI,lli);
8059 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8060 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8061 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8062 llc[2] = 4;
8063 add_p(plci, LLC, llc);
8064 dlc[0] = 2;
8065 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8066 dlc[3] = 3; /* Addr A */
8067 dlc[4] = 1; /* Addr B */
8068 dlc[5] = 7; /* modulo mode */
8069 dlc[6] = 7; /* window size */
8070 dlc[7] = 0; /* XID len Lo */
8071 dlc[8] = 0; /* XID len Hi */
8072 for (i = 0; i < bp_parms[4].length; i++)
8073 dlc[9+i] = bp_parms[4].info[1+i];
8074 dlc[0] = (byte)(8 + bp_parms[4].length);
8075 add_p(plci, DLC, dlc);
8076 for (i = 0; i < bp_parms[5].length; i++)
8077 nlc[1+i] = bp_parms[5].info[1+i];
8078 nlc[0] = (byte)(bp_parms[5].length);
8079 add_p(plci, NLC, nlc);
8080 return 0;
8085 if ((GET_WORD(bp_parms[1].info) >= 32)
8086 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8087 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8088 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8091 return _B2_NOT_SUPPORTED;
8093 if ((GET_WORD(bp_parms[2].info) >= 32)
8094 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8096 return _B3_NOT_SUPPORTED;
8098 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8099 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8100 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8101 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8103 return (add_modem_b23 (plci, bp_parms));
8106 add_p(plci,LLI,lli);
8108 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8109 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8110 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8112 if(bp_parms[6].length)
8114 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8116 return _WRONG_MESSAGE_FORMAT;
8118 switch(GET_WORD(global_config[0].info))
8120 case 1:
8121 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8122 break;
8123 case 2:
8124 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8125 break;
8128 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8131 if (plci->B2_prot == B2_PIAFS)
8132 llc[1] = PIAFS_CRC;
8133 else
8134 /* IMPLEMENT_PIAFS */
8136 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8137 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8139 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8141 add_p(plci, LLC, llc);
8143 dlc[0] = 2;
8144 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8145 header[GET_WORD(bp_parms[2].info)]);
8147 b1_config = &bp_parms[3];
8148 nlc[0] = 0;
8149 if(plci->B3_prot == 4
8150 || plci->B3_prot == 5)
8152 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8153 nlc[0] = sizeof(T30_INFO);
8154 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8155 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8156 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8157 if(b1_config->length>=2)
8159 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8162 b2_config = &bp_parms[4];
8165 if (llc[1] == PIAFS_CRC)
8167 if (plci->B3_prot != B3_TRANSPARENT)
8169 return _B_STACK_NOT_SUPPORTED;
8171 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8172 return _WRONG_MESSAGE_FORMAT;
8174 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8175 dlc[3] = 0; /* Addr A */
8176 dlc[4] = 0; /* Addr B */
8177 dlc[5] = 0; /* modulo mode */
8178 dlc[6] = 0; /* window size */
8179 if (b2_config->length >= 7){
8180 dlc[ 7] = 7;
8181 dlc[ 8] = 0;
8182 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8183 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8184 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8185 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8186 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8187 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8188 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8189 dlc[ 0] = 15;
8190 if(b2_config->length >= 8) { /* PIAFS control abilities */
8191 dlc[ 7] = 10;
8192 dlc[16] = 2; /* Length of PIAFS extention */
8193 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8194 dlc[18] = b2_config_parms[4].info[0]; /* value */
8195 dlc[ 0] = 18;
8198 else /* default values, 64K, variable, no compression */
8200 dlc[ 7] = 7;
8201 dlc[ 8] = 0;
8202 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8203 dlc[10] = 0x03; /* V.42bis P0 */
8204 dlc[11] = 0; /* V.42bis P0 */
8205 dlc[12] = 0; /* V.42bis P1 */
8206 dlc[13] = 0; /* V.42bis P1 */
8207 dlc[14] = 0; /* V.42bis P2 */
8208 dlc[15] = 0; /* V.42bis P2 */
8209 dlc[ 0] = 15;
8211 add_p(plci, DLC, dlc);
8213 else
8215 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8217 if (plci->B3_prot != B3_TRANSPARENT)
8218 return _B_STACK_NOT_SUPPORTED;
8220 dlc[0] = 6;
8221 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8222 dlc[3] = 0x08;
8223 dlc[4] = 0x01;
8224 dlc[5] = 127;
8225 dlc[6] = 7;
8226 if (b2_config->length != 0)
8228 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8229 return _WRONG_MESSAGE_FORMAT;
8231 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8232 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8233 if (b2_config->info[3] != 128)
8235 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8236 return _B2_PARM_NOT_SUPPORTED;
8238 dlc[5] = (byte)(b2_config->info[3] - 1);
8239 dlc[6] = b2_config->info[4];
8240 if(llc[1]==V120_V42BIS){
8241 if (b2_config->length >= 10){
8242 dlc[ 7] = 6;
8243 dlc[ 8] = 0;
8244 dlc[ 9] = b2_config_parms[4].info[0];
8245 dlc[10] = b2_config_parms[4].info[1];
8246 dlc[11] = b2_config_parms[5].info[0];
8247 dlc[12] = b2_config_parms[5].info[1];
8248 dlc[13] = b2_config_parms[6].info[0];
8249 dlc[14] = b2_config_parms[6].info[1];
8250 dlc[ 0] = 14;
8251 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8252 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8253 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8255 else {
8256 dlc[ 6] = 14;
8261 else
8263 if(b2_config->length)
8265 dbug(1,dprintf("B2-Config"));
8266 if(llc[1]==X75_V42BIS){
8267 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8269 return _WRONG_MESSAGE_FORMAT;
8272 else {
8273 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8275 return _WRONG_MESSAGE_FORMAT;
8278 /* if B2 Protocol is LAPD, b2_config structure is different */
8279 if(llc[1]==6)
8281 dlc[0] = 4;
8282 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8283 else dlc[2] = 0x01;
8284 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8286 SAPI = b2_config->info[2]; /* SAPI */
8288 dlc[1] = SAPI;
8289 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8291 dlc[3] = 127; /* Mode */
8293 else
8295 dlc[3] = 7; /* Mode */
8298 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8299 else dlc[4] = 1;
8300 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8301 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8303 else
8305 dlc[0] = (byte)(b2_config_parms[4].length+6);
8306 dlc[3] = b2_config->info[1];
8307 dlc[4] = b2_config->info[2];
8308 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8309 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8310 return _B2_PARM_NOT_SUPPORTED;
8313 dlc[5] = (byte)(b2_config->info[3]-1);
8314 dlc[6] = b2_config->info[4];
8315 if(dlc[6]>dlc[5]){
8316 dbug(1,dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8317 return _B2_PARM_NOT_SUPPORTED;
8320 if(llc[1]==X75_V42BIS) {
8321 if (b2_config->length >= 10){
8322 dlc[ 7] = 6;
8323 dlc[ 8] = 0;
8324 dlc[ 9] = b2_config_parms[4].info[0];
8325 dlc[10] = b2_config_parms[4].info[1];
8326 dlc[11] = b2_config_parms[5].info[0];
8327 dlc[12] = b2_config_parms[5].info[1];
8328 dlc[13] = b2_config_parms[6].info[0];
8329 dlc[14] = b2_config_parms[6].info[1];
8330 dlc[ 0] = 14;
8331 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8332 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8333 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8335 else {
8336 dlc[ 6] = 14;
8340 else {
8341 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8342 for(i=0; i<b2_config_parms[4].length; i++)
8343 dlc[11+i] = b2_config_parms[4].info[1+i];
8348 add_p(plci, DLC, dlc);
8350 b3_config = &bp_parms[5];
8351 if(b3_config->length)
8353 if(plci->B3_prot == 4
8354 || plci->B3_prot == 5)
8356 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8358 return _WRONG_MESSAGE_FORMAT;
8360 i = GET_WORD((byte *)(b3_config_parms[0].info));
8361 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8362 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8363 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8364 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8365 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8366 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8367 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8370 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8371 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8373 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8374 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8375 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8378 ((T30_INFO *)&nlc[1])->recording_properties =
8379 T30_RECORDING_WIDTH_ISO_A3 |
8380 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8381 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8383 if(plci->B3_prot == 5)
8385 if (i & 0x0002) /* Accept incoming fax-polling requests */
8386 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8387 if (i & 0x2000) /* Do not use MR compression */
8388 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8389 if (i & 0x4000) /* Do not use MMR compression */
8390 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8391 if (i & 0x8000) /* Do not use ECM */
8392 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8393 if (plci->fax_connect_info_length != 0)
8395 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8396 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8397 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8398 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8399 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8402 /* copy station id to NLC */
8403 for(i=0; i < T30_MAX_STATION_ID_LENGTH; i++)
8405 if(i<b3_config_parms[2].length)
8407 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8409 else
8411 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8414 ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8415 /* copy head line to NLC */
8416 if(b3_config_parms[3].length)
8419 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8420 if (pos != 0)
8422 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8423 pos = 0;
8424 else
8426 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8427 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8428 len = (byte)b3_config_parms[2].length;
8429 if (len > 20)
8430 len = 20;
8431 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8433 for (i = 0; i < len; i++)
8434 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8435 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8436 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8441 len = (byte)b3_config_parms[3].length;
8442 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8443 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8444 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8445 nlc[0] += (byte)(pos + len);
8446 for (i = 0; i < len; i++)
8447 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8448 } else
8449 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8451 plci->nsf_control_bits = 0;
8452 if(plci->B3_prot == 5)
8454 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8455 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8457 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8459 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8460 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8462 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8464 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8465 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8467 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8470 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8471 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8472 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8474 len = nlc[0];
8475 pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8476 if (pos < plci->fax_connect_info_length)
8478 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8479 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8481 else
8482 nlc[++len] = 0;
8483 if (pos < plci->fax_connect_info_length)
8485 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8486 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8488 else
8489 nlc[++len] = 0;
8490 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8491 & (1L << PRIVATE_FAX_NONSTANDARD))
8493 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8495 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8496 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8497 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8498 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8500 else
8502 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8504 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8505 nlc[++len] = 0;
8507 else
8509 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8510 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8511 nlc[++len] = (byte)(b3_config_parms[4].length);
8512 for (i = 0; i < b3_config_parms[4].length; i++)
8513 nlc[++len] = b3_config_parms[4].info[1+i];
8517 nlc[0] = len;
8518 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8519 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8521 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8526 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8527 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8528 for (i = 0; i < len; i++)
8529 plci->fax_connect_info_buffer[i] = nlc[1+i];
8530 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8531 i += ((T30_INFO *)&nlc[1])->head_line_len;
8532 while (i < nlc[0])
8533 plci->fax_connect_info_buffer[len++] = nlc[++i];
8534 plci->fax_connect_info_length = len;
8536 else
8538 nlc[0] = 14;
8539 if(b3_config->length!=16)
8540 return _B3_PARM_NOT_SUPPORTED;
8541 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8542 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8543 return _B3_PARM_NOT_SUPPORTED;
8544 nlc[13] = b3_config->info[13];
8545 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8546 return _B3_PARM_NOT_SUPPORTED;
8547 nlc[14] = b3_config->info[15];
8550 else
8552 if (plci->B3_prot == 4
8553 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8555 add_p(plci, NLC, nlc);
8556 return 0;
8559 /*----------------------------------------------------------------*/
8560 /* make the same as add_b23, but only for the modem related */
8561 /* L2 and L3 B-Chan protocol. */
8562 /* */
8563 /* Enabled L2 and L3 Configurations: */
8564 /* If L1 == Modem all negotiation */
8565 /* only L2 == Modem with full negotiation is allowed */
8566 /* If L1 == Modem async or sync */
8567 /* only L2 == Transparent is allowed */
8568 /* L3 == Modem or L3 == Transparent are allowed */
8569 /* B2 Configuration for modem: */
8570 /* word : enable/disable compression, bitoptions */
8571 /* B3 Configuration for modem: */
8572 /* empty */
8573 /*----------------------------------------------------------------*/
8574 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8576 static byte lli[12] = {1,1};
8577 static byte llc[3] = {2,0,0};
8578 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8579 API_PARSE mdm_config[2];
8580 word i;
8581 word b2_config = 0;
8583 for(i=0;i<2;i++) mdm_config[i].length = 0;
8584 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8586 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8587 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8588 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8589 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8591 return (_B_STACK_NOT_SUPPORTED);
8593 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8594 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8596 return (_B_STACK_NOT_SUPPORTED);
8599 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8600 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8602 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8604 if (api_parse (&bp_parms[4].info[1],
8605 (word)bp_parms[4].length, "w",
8606 mdm_config))
8608 return (_WRONG_MESSAGE_FORMAT);
8610 b2_config = GET_WORD(mdm_config[0].info);
8613 /* OK, L2 is modem */
8615 lli[0] = 1;
8616 lli[1] = 1;
8617 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8618 lli[1] |= 2;
8619 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8620 lli[1] |= 4;
8622 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8623 lli[1] |= 0x10;
8624 if (plci->rx_dma_descriptor <= 0) {
8625 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8626 if (plci->rx_dma_descriptor >= 0)
8627 plci->rx_dma_descriptor++;
8629 if (plci->rx_dma_descriptor > 0) {
8630 lli[1] |= 0x40;
8631 lli[0] = 6;
8632 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8633 lli[3] = (byte)plci->rx_dma_magic;
8634 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8635 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8636 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8640 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8641 lli[1] |= 0x20;
8644 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8645 /*V42*/ 10 : /*V42_IN*/ 9;
8646 llc[2] = 4; /* pass L3 always transparent */
8647 add_p(plci, LLI, lli);
8648 add_p(plci, LLC, llc);
8649 i = 1;
8650 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8651 i += 2;
8652 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8654 if (bp_parms[4].length)
8656 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8657 dlc[i++] = 3; /* Addr A */
8658 dlc[i++] = 1; /* Addr B */
8659 dlc[i++] = 7; /* modulo mode */
8660 dlc[i++] = 7; /* window size */
8661 dlc[i++] = 0; /* XID len Lo */
8662 dlc[i++] = 0; /* XID len Hi */
8664 if (b2_config & MDM_B2_DISABLE_V42bis)
8666 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8668 if (b2_config & MDM_B2_DISABLE_MNP)
8670 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8672 if (b2_config & MDM_B2_DISABLE_TRANS)
8674 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8676 if (b2_config & MDM_B2_DISABLE_V42)
8678 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8680 if (b2_config & MDM_B2_DISABLE_COMP)
8682 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8684 i++;
8687 else
8689 dlc[i++] = 3; /* Addr A */
8690 dlc[i++] = 1; /* Addr B */
8691 dlc[i++] = 7; /* modulo mode */
8692 dlc[i++] = 7; /* window size */
8693 dlc[i++] = 0; /* XID len Lo */
8694 dlc[i++] = 0; /* XID len Hi */
8695 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8696 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8697 DLC_MODEMPROT_DISABLE_V42_DETECT |
8698 DLC_MODEMPROT_DISABLE_COMPRESSION;
8700 dlc[0] = (byte)(i - 1);
8701 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8702 add_p(plci, DLC, dlc);
8703 return (0);
8707 /*------------------------------------------------------------------*/
8708 /* send a request for the signaling entity */
8709 /*------------------------------------------------------------------*/
8711 static void sig_req(PLCI *plci, byte req, byte Id)
8713 if(!plci) return;
8714 if(plci->adapter->adapter_disabled) return;
8715 dbug(1,dprintf("sig_req(%x)",req));
8716 if (req == REMOVE)
8717 plci->sig_remove_id = plci->Sig.Id;
8718 if(plci->req_in==plci->req_in_start) {
8719 plci->req_in +=2;
8720 plci->RBuffer[plci->req_in++] = 0;
8722 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8723 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8724 plci->RBuffer[plci->req_in++] = req; /* request */
8725 plci->RBuffer[plci->req_in++] = 0; /* channel */
8726 plci->req_in_start = plci->req_in;
8729 /*------------------------------------------------------------------*/
8730 /* send a request for the network layer entity */
8731 /*------------------------------------------------------------------*/
8733 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8735 if(!plci) return;
8736 if(plci->adapter->adapter_disabled) return;
8737 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8738 if (req == REMOVE)
8740 plci->nl_remove_id = plci->NL.Id;
8741 ncci_remove (plci, 0, (byte)(ncci != 0));
8742 ncci = 0;
8744 if(plci->req_in==plci->req_in_start) {
8745 plci->req_in +=2;
8746 plci->RBuffer[plci->req_in++] = 0;
8748 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8749 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8750 plci->RBuffer[plci->req_in++] = req; /* request */
8751 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8752 plci->req_in_start = plci->req_in;
8755 static void send_req(PLCI *plci)
8757 ENTITY * e;
8758 word l;
8759 /* word i; */
8761 if(!plci) return;
8762 if(plci->adapter->adapter_disabled) return;
8763 channel_xmit_xon (plci);
8765 /* if nothing to do, return */
8766 if(plci->req_in==plci->req_out) return;
8767 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8769 if(plci->nl_req || plci->sig_req) return;
8771 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8772 plci->req_out += 2;
8773 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8774 plci->req_out += l;
8775 if(plci->RBuffer[plci->req_out]==1)
8777 e = &plci->NL;
8778 plci->req_out++;
8779 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8780 e->ReqCh = plci->RBuffer[plci->req_out++];
8781 if(!(e->Id & 0x1f))
8783 e->Id = NL_ID;
8784 plci->RBuffer[plci->req_out-4] = CAI;
8785 plci->RBuffer[plci->req_out-3] = 1;
8786 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8787 plci->RBuffer[plci->req_out-1] = 0;
8788 l+=3;
8789 plci->nl_global_req = plci->nl_req;
8791 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8793 else
8795 e = &plci->Sig;
8796 if(plci->RBuffer[plci->req_out])
8797 e->Id = plci->RBuffer[plci->req_out];
8798 plci->req_out++;
8799 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8800 e->ReqCh = plci->RBuffer[plci->req_out++];
8801 if(!(e->Id & 0x1f))
8802 plci->sig_global_req = plci->sig_req;
8803 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8805 plci->XData[0].PLength = l;
8806 e->X = plci->XData;
8807 plci->adapter->request(e);
8808 dbug(1,dprintf("send_ok"));
8811 static void send_data(PLCI *plci)
8813 DIVA_CAPI_ADAPTER * a;
8814 DATA_B3_DESC * data;
8815 NCCI *ncci_ptr;
8816 word ncci;
8818 if (!plci->nl_req && plci->ncci_ring_list)
8820 a = plci->adapter;
8821 ncci = plci->ncci_ring_list;
8824 ncci = a->ncci_next[ncci];
8825 ncci_ptr = &(a->ncci[ncci]);
8826 if (!(a->ncci_ch[ncci]
8827 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8829 if (ncci_ptr->data_pending)
8831 if ((a->ncci_state[ncci] == CONNECTED)
8832 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8833 || (plci->send_disc == ncci))
8835 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8836 if ((plci->B2_prot == B2_V120_ASYNC)
8837 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8838 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8840 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8841 plci->NData[1].PLength = data->Length;
8842 if (data->Flags & 0x10)
8843 plci->NData[0].P = v120_break_header;
8844 else
8845 plci->NData[0].P = v120_default_header;
8846 plci->NData[0].PLength = 1 ;
8847 plci->NL.XNum = 2;
8848 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8850 else
8852 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8853 plci->NData[0].PLength = data->Length;
8854 if (data->Flags & 0x10)
8855 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8857 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8858 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8860 else
8861 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8863 plci->NL.X = plci->NData;
8864 plci->NL.ReqCh = a->ncci_ch[ncci];
8865 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8866 plci->data_sent = true;
8867 plci->data_sent_ptr = data->P;
8868 a->request(&plci->NL);
8870 else {
8871 cleanup_ncci_data (plci, ncci);
8874 else if (plci->send_disc == ncci)
8876 /* dprintf("N_DISC"); */
8877 plci->NData[0].PLength = 0;
8878 plci->NL.ReqCh = a->ncci_ch[ncci];
8879 plci->NL.Req = plci->nl_req = N_DISC;
8880 a->request(&plci->NL);
8881 plci->command = _DISCONNECT_B3_R;
8882 plci->send_disc = 0;
8885 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8886 plci->ncci_ring_list = ncci;
8890 static void listen_check(DIVA_CAPI_ADAPTER *a)
8892 word i,j;
8893 PLCI * plci;
8894 byte activnotifiedcalls = 0;
8896 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8897 if (!remove_started && !a->adapter_disabled)
8899 for(i=0;i<a->max_plci;i++)
8901 plci = &(a->plci[i]);
8902 if(plci->notifiedcall) activnotifiedcalls++;
8904 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8906 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8907 if((j=get_plci(a))) {
8908 a->listen_active++;
8909 plci = &a->plci[j-1];
8910 plci->State = LISTENING;
8912 add_p(plci,OAD,"\x01\xfd");
8914 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8916 add_p(plci,CAI,"\x01\xc0");
8917 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8918 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8919 add_p(plci,SHIFT|6,NULL);
8920 add_p(plci,SIN,"\x02\x00\x00");
8921 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8922 sig_req(plci,ASSIGN,DSIG_ID);
8923 send_req(plci);
8929 /*------------------------------------------------------------------*/
8930 /* functions for all parameters sent in INDs */
8931 /*------------------------------------------------------------------*/
8933 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8935 word ploc; /* points to current location within packet */
8936 byte w;
8937 byte wlen;
8938 byte codeset,lock;
8939 byte * in;
8940 word i;
8941 word code;
8942 word mIEindex = 0;
8943 ploc = 0;
8944 codeset = 0;
8945 lock = 0;
8947 in = plci->Sig.RBuffer->P;
8948 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8949 { /* element but parms array is larger */
8950 parms[i] = (byte *)"";
8952 for(i=0; i<multiIEsize; i++)
8954 parms[i] = (byte *)"";
8957 while(ploc<plci->Sig.RBuffer->length-1) {
8959 /* read information element id and length */
8960 w = in[ploc];
8962 if(w & 0x80) {
8963 /* w &=0xf0; removed, cannot detect congestion levels */
8964 /* upper 4 bit masked with w==SHIFT now */
8965 wlen = 0;
8967 else {
8968 wlen = (byte)(in[ploc+1]+1);
8970 /* check if length valid (not exceeding end of packet) */
8971 if((ploc+wlen) > 270) return ;
8972 if(lock & 0x80) lock &=0x7f;
8973 else codeset = lock;
8975 if((w&0xf0)==SHIFT) {
8976 codeset = in[ploc];
8977 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8978 codeset &=7;
8979 lock |=0x80;
8981 else {
8982 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8983 else code = w;
8984 code |= (codeset<<8);
8986 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8988 if(i<parms_id[0]+1) {
8989 if(!multiIEsize) { /* with multiIEs use next field index, */
8990 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8993 parms[mIEindex] = &in[ploc+1];
8994 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8995 if(parms_id[i]==OAD
8996 || parms_id[i]==CONN_NR
8997 || parms_id[i]==CAD) {
8998 if(in[ploc+2] &0x80) {
8999 in[ploc+0] = (byte)(in[ploc+1]+1);
9000 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
9001 in[ploc+2] = 0x80;
9002 parms[mIEindex] = &in[ploc];
9005 mIEindex++; /* effects multiIEs only */
9009 ploc +=(wlen+1);
9011 return ;
9014 /*------------------------------------------------------------------*/
9015 /* try to match a cip from received BC and HLC */
9016 /*------------------------------------------------------------------*/
9018 static byte ie_compare(byte *ie1, byte *ie2)
9020 word i;
9021 if(!ie1 || ! ie2) return false;
9022 if(!ie1[0]) return false;
9023 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9024 return true;
9027 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9029 word i;
9030 word j;
9032 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9034 for(j=16;j<29 &&
9035 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9036 if(j==29) return i;
9037 return j;
9041 static byte AddInfo(byte **add_i,
9042 byte **fty_i,
9043 byte *esc_chi,
9044 byte *facility)
9046 byte i;
9047 byte j;
9048 byte k;
9049 byte flen;
9050 byte len=0;
9051 /* facility is a nested structure */
9052 /* FTY can be more than once */
9054 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9056 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9059 else
9061 add_i[0] = (byte *)"";
9063 if(!fty_i[0][0])
9065 add_i[3] = (byte *)"";
9067 else
9068 { /* facility array found */
9069 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9071 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9072 len += fty_i[i][0];
9073 len += 2;
9074 flen=fty_i[i][0];
9075 facility[j++]=0x1c; /* copy fac IE */
9076 for(k=0;k<=flen;k++,j++)
9078 facility[j]=fty_i[i][k];
9079 /* dbug(1,dprintf("%x ",facility[j])); */
9082 facility[0] = len;
9083 add_i[3] = facility;
9085 /* dbug(1,dprintf("FacArrLen=%d ",len)); */
9086 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9087 len += 4; /* calculate length of all */
9088 return(len);
9091 /*------------------------------------------------------------------*/
9092 /* voice and codec features */
9093 /*------------------------------------------------------------------*/
9095 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9097 byte voice_chi[] = "\x02\x18\x01";
9098 byte channel;
9100 channel = chi[chi[0]]&0x3;
9101 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9102 voice_chi[2] = (channel) ? channel : 1;
9103 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9104 add_p(plci,ESC,voice_chi); /* Channel */
9105 sig_req(plci,TEL_CTRL,0);
9106 send_req(plci);
9107 if(a->AdvSignalPLCI)
9109 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9113 static void VoiceChannelOff(PLCI *plci)
9115 dbug(1,dprintf("ExtDevOFF"));
9116 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9117 sig_req(plci,TEL_CTRL,0);
9118 send_req(plci);
9119 if(plci->adapter->AdvSignalPLCI)
9121 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9126 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9127 byte hook_listen)
9129 word j;
9130 PLCI *splci;
9132 /* check if hardware supports handset with hook states (adv.codec) */
9133 /* or if just a on board codec is supported */
9134 /* the advanced codec plci is just for internal use */
9136 /* diva Pro with on-board codec: */
9137 if(a->profile.Global_Options & HANDSET)
9139 /* new call, but hook states are already signalled */
9140 if(a->AdvCodecFLAG)
9142 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9144 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9145 return 0x2001; /* codec in use by another application */
9147 if(plci!=NULL)
9149 a->AdvSignalPLCI = plci;
9150 plci->tel=ADV_VOICE;
9152 return 0; /* adv codec still used */
9154 if((j=get_plci(a)))
9156 splci = &a->plci[j-1];
9157 splci->tel = CODEC_PERMANENT;
9158 /* hook_listen indicates if a facility_req with handset/hook support */
9159 /* was sent. Otherwise if just a call on an external device was made */
9160 /* the codec will be used but the hook info will be discarded (just */
9161 /* the external controller is in use */
9162 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9163 else
9165 splci->State = ADVANCED_VOICE_NOSIG;
9166 if(plci)
9168 plci->spoofed_msg = SPOOFING_REQUIRED;
9170 /* indicate D-ch connect if */
9171 } /* codec is connected OK */
9172 if(plci!=NULL)
9174 a->AdvSignalPLCI = plci;
9175 plci->tel=ADV_VOICE;
9177 a->AdvSignalAppl = appl;
9178 a->AdvCodecFLAG = true;
9179 a->AdvCodecPLCI = splci;
9180 add_p(splci,CAI,"\x01\x15");
9181 add_p(splci,LLI,"\x01\x00");
9182 add_p(splci,ESC,"\x02\x18\x00");
9183 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184 splci->internal_command = PERM_COD_ASSIGN;
9185 dbug(1,dprintf("Codec Assign"));
9186 sig_req(splci,ASSIGN,DSIG_ID);
9187 send_req(splci);
9189 else
9191 return 0x2001; /* wrong state, no more plcis */
9194 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9196 if(hook_listen) return 0x300B; /* Facility not supported */
9197 /* no hook with SCOM */
9198 if(plci!=NULL) plci->tel = CODEC;
9199 dbug(1,dprintf("S/SCOM codec"));
9200 /* first time we use the scom-s codec we must shut down the internal */
9201 /* handset application of the card. This can be done by an assign with */
9202 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9203 if(!a->scom_appl_disable){
9204 if((j=get_plci(a))) {
9205 splci = &a->plci[j-1];
9206 add_p(splci,CAI,"\x01\x80");
9207 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9208 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9209 send_req(splci);
9210 a->scom_appl_disable = true;
9212 else{
9213 return 0x2001; /* wrong state, no more plcis */
9217 else return 0x300B; /* Facility not supported */
9219 return 0;
9223 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9226 dbug(1,dprintf("CodecIdCheck"));
9228 if(a->AdvSignalPLCI == plci)
9230 dbug(1,dprintf("PLCI owns codec"));
9231 VoiceChannelOff(a->AdvCodecPLCI);
9232 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9234 dbug(1,dprintf("remove temp codec PLCI"));
9235 plci_remove(a->AdvCodecPLCI);
9236 a->AdvCodecFLAG = 0;
9237 a->AdvCodecPLCI = NULL;
9238 a->AdvSignalAppl = NULL;
9240 a->AdvSignalPLCI = NULL;
9244 /* -------------------------------------------------------------------
9245 Ask for physical address of card on PCI bus
9246 ------------------------------------------------------------------- */
9247 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9248 IDI_SYNC_REQ * preq) {
9249 a->sdram_bar = 0;
9250 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9251 ENTITY * e = (ENTITY *)preq;
9253 e->user[0] = a->Id - 1;
9254 preq->xdi_sdram_bar.info.bar = 0;
9255 preq->xdi_sdram_bar.Req = 0;
9256 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9258 (*(a->request))(e);
9260 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9261 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9265 /* -------------------------------------------------------------------
9266 Ask XDI about extended features
9267 ------------------------------------------------------------------- */
9268 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9269 IDI_SYNC_REQ * preq;
9270 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9272 char features[4];
9273 preq = (IDI_SYNC_REQ *)&buffer[0];
9275 if (!diva_xdi_extended_features) {
9276 ENTITY * e = (ENTITY *)preq;
9277 diva_xdi_extended_features |= 0x80000000;
9279 e->user[0] = a->Id - 1;
9280 preq->xdi_extended_features.Req = 0;
9281 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9282 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9283 preq->xdi_extended_features.info.features = &features[0];
9285 (*(a->request))(e);
9287 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9289 Check features located in the byte '0'
9291 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9292 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9294 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9295 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9296 dbug(1,dprintf("XDI provides RxDMA"));
9298 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9299 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9301 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9302 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9303 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9309 diva_ask_for_xdi_sdram_bar (a, preq);
9312 /*------------------------------------------------------------------*/
9313 /* automatic law */
9314 /*------------------------------------------------------------------*/
9315 /* called from OS specific part after init time to get the Law */
9316 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9317 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9319 word j;
9320 PLCI *splci;
9322 if(a->automatic_law) {
9323 return;
9325 if((j=get_plci(a))) {
9326 diva_get_extended_adapter_features (a);
9327 splci = &a->plci[j-1];
9328 a->automatic_lawPLCI = splci;
9329 a->automatic_law = 1;
9330 add_p(splci,CAI,"\x01\x80");
9331 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9332 splci->internal_command = USELAW_REQ;
9333 splci->command = 0;
9334 splci->number = 0;
9335 sig_req(splci,ASSIGN,DSIG_ID);
9336 send_req(splci);
9340 /* called from OS specific part if an application sends an Capi20Release */
9341 word CapiRelease(word Id)
9343 word i, j, appls_found;
9344 PLCI *plci;
9345 APPL *this;
9346 DIVA_CAPI_ADAPTER *a;
9348 if (!Id)
9350 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9351 return (_WRONG_APPL_ID);
9354 this = &application[Id-1]; /* get application pointer */
9356 for(i=0,appls_found=0; i<max_appl; i++)
9358 if(application[i].Id) /* an application has been found */
9360 appls_found++;
9364 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9366 a = &adapter[i];
9367 if (a->request)
9369 a->Info_Mask[Id-1] = 0;
9370 a->CIP_Mask[Id-1] = 0;
9371 a->Notification_Mask[Id-1] = 0;
9372 a->codec_listen[Id-1] = NULL;
9373 a->requested_options_table[Id-1] = 0;
9374 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9375 { /* with this application */
9376 plci = &a->plci[j];
9377 if(plci->Id) /* if plci owns no application */
9378 { /* it may be not jet connected */
9379 if(plci->State==INC_CON_PENDING
9380 || plci->State==INC_CON_ALERT)
9382 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9384 clear_c_ind_mask_bit (plci, (word)(Id-1));
9385 if(c_ind_mask_empty (plci))
9387 sig_req(plci,HANGUP,0);
9388 send_req(plci);
9389 plci->State = OUTG_DIS_PENDING;
9393 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9395 clear_c_ind_mask_bit (plci, (word)(Id-1));
9396 if(c_ind_mask_empty (plci))
9398 if(!plci->appl)
9400 plci_remove(plci);
9401 plci->State = IDLE;
9405 if(plci->appl==this)
9407 plci->appl = NULL;
9408 plci_remove(plci);
9409 plci->State = IDLE;
9413 listen_check(a);
9415 if(a->flag_dynamic_l1_down)
9417 if(appls_found==1) /* last application does a capi release */
9419 if((j=get_plci(a)))
9421 plci = &a->plci[j-1];
9422 plci->command = 0;
9423 add_p(plci,OAD,"\x01\xfd");
9424 add_p(plci,CAI,"\x01\x80");
9425 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9426 add_p(plci,SHIFT|6,NULL);
9427 add_p(plci,SIN,"\x02\x00\x00");
9428 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9429 sig_req(plci,ASSIGN,DSIG_ID);
9430 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9431 sig_req(plci,SIG_CTRL,0);
9432 send_req(plci);
9436 if(a->AdvSignalAppl==this)
9438 this->NullCREnable = false;
9439 if (a->AdvCodecPLCI)
9441 plci_remove(a->AdvCodecPLCI);
9442 a->AdvCodecPLCI->tel = 0;
9443 a->AdvCodecPLCI->adv_nl = 0;
9445 a->AdvSignalAppl = NULL;
9446 a->AdvSignalPLCI = NULL;
9447 a->AdvCodecFLAG = 0;
9448 a->AdvCodecPLCI = NULL;
9453 this->Id = 0;
9455 return GOOD;
9458 static word plci_remove_check(PLCI *plci)
9460 if(!plci) return true;
9461 if(!plci->NL.Id && c_ind_mask_empty (plci))
9463 if(plci->Sig.Id == 0xff)
9464 plci->Sig.Id = 0;
9465 if(!plci->Sig.Id)
9467 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9468 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9469 if (plci->Id)
9471 CodecIdCheck(plci->adapter, plci);
9472 clear_b1_config (plci);
9473 ncci_remove (plci, 0, false);
9474 plci_free_msg_in_queue (plci);
9475 channel_flow_control_remove (plci);
9476 plci->Id = 0;
9477 plci->State = IDLE;
9478 plci->channels = 0;
9479 plci->appl = NULL;
9480 plci->notifiedcall = 0;
9482 listen_check(plci->adapter);
9483 return true;
9486 return false;
9490 /*------------------------------------------------------------------*/
9492 static byte plci_nl_busy (PLCI *plci)
9494 /* only applicable for non-multiplexed protocols */
9495 return (plci->nl_req
9496 || (plci->ncci_ring_list
9497 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9498 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9502 /*------------------------------------------------------------------*/
9503 /* DTMF facilities */
9504 /*------------------------------------------------------------------*/
9507 static struct
9509 byte send_mask;
9510 byte listen_mask;
9511 byte character;
9512 byte code;
9513 } dtmf_digit_map[] =
9515 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9516 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9517 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9518 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9519 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9520 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9521 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9522 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9523 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9524 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9525 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9526 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9527 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9528 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9529 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9530 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9531 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9532 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9533 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9534 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9536 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9537 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9538 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9539 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9540 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9541 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9542 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9543 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9544 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9545 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9546 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9547 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9548 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9549 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9550 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9551 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9552 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9553 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9554 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9555 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9556 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9557 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9558 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9559 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9560 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9561 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9562 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9563 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9564 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9565 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9566 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9567 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9568 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9569 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9570 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9571 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9572 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9573 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9574 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9575 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9576 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9577 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9578 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9579 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9580 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9581 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9582 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9583 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9584 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9585 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9586 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9587 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9591 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9594 static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9596 word min_digit_duration, min_gap_duration;
9598 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9599 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9600 (char *)(FILE_), __LINE__, enable_mask));
9602 if (enable_mask != 0)
9604 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9605 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9606 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9607 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9608 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9609 plci->NData[0].PLength = 5;
9611 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9612 plci->NData[0].PLength += 2;
9613 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9616 else
9618 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9619 plci->NData[0].PLength = 1;
9621 capidtmf_recv_disable (&(plci->capidtmf_state));
9624 plci->NData[0].P = plci->internal_req_buffer;
9625 plci->NL.X = plci->NData;
9626 plci->NL.ReqCh = 0;
9627 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9628 plci->adapter->request (&plci->NL);
9632 static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9634 word w, i;
9636 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9637 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9638 (char *)(FILE_), __LINE__, digit_count));
9640 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9641 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9642 PUT_WORD (&plci->internal_req_buffer[1], w);
9643 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9644 PUT_WORD (&plci->internal_req_buffer[3], w);
9645 for (i = 0; i < digit_count; i++)
9647 w = 0;
9648 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9649 && (digit_buffer[i] != dtmf_digit_map[w].character))
9651 w++;
9653 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9654 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9656 plci->NData[0].PLength = 5 + digit_count;
9657 plci->NData[0].P = plci->internal_req_buffer;
9658 plci->NL.X = plci->NData;
9659 plci->NL.ReqCh = 0;
9660 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9661 plci->adapter->request (&plci->NL);
9665 static void dtmf_rec_clear_config (PLCI *plci)
9668 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9669 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9670 (char *)(FILE_), __LINE__));
9672 plci->dtmf_rec_active = 0;
9673 plci->dtmf_rec_pulse_ms = 0;
9674 plci->dtmf_rec_pause_ms = 0;
9676 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9681 static void dtmf_send_clear_config (PLCI *plci)
9684 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9685 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9686 (char *)(FILE_), __LINE__));
9688 plci->dtmf_send_requests = 0;
9689 plci->dtmf_send_pulse_ms = 0;
9690 plci->dtmf_send_pause_ms = 0;
9694 static void dtmf_prepare_switch (dword Id, PLCI *plci)
9697 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9698 UnMapId (Id), (char *)(FILE_), __LINE__));
9700 while (plci->dtmf_send_requests != 0)
9701 dtmf_confirmation (Id, plci);
9705 static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9708 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9709 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9711 return (GOOD);
9715 static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9717 word Info;
9719 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9720 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9722 Info = GOOD;
9723 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9725 switch (plci->adjust_b_state)
9727 case ADJUST_B_RESTORE_DTMF_1:
9728 plci->internal_command = plci->adjust_b_command;
9729 if (plci_nl_busy (plci))
9731 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9732 break;
9734 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9735 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9736 break;
9737 case ADJUST_B_RESTORE_DTMF_2:
9738 if ((Rc != OK) && (Rc != OK_FC))
9740 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9741 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9742 Info = _WRONG_STATE;
9743 break;
9745 break;
9748 return (Info);
9752 static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9754 word internal_command, Info;
9755 byte mask;
9756 byte result[4];
9758 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9759 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9760 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9761 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9763 Info = GOOD;
9764 result[0] = 2;
9765 PUT_WORD (&result[1], DTMF_SUCCESS);
9766 internal_command = plci->internal_command;
9767 plci->internal_command = 0;
9768 mask = 0x01;
9769 switch (plci->dtmf_cmd)
9772 case DTMF_LISTEN_TONE_START:
9773 mask <<= 1;
9774 case DTMF_LISTEN_MF_START:
9775 mask <<= 1;
9777 case DTMF_LISTEN_START:
9778 switch (internal_command)
9780 default:
9781 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9782 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9783 case DTMF_COMMAND_1:
9784 if (adjust_b_process (Id, plci, Rc) != GOOD)
9786 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9787 UnMapId (Id), (char *)(FILE_), __LINE__));
9788 Info = _FACILITY_NOT_SUPPORTED;
9789 break;
9791 if (plci->internal_command)
9792 return;
9793 case DTMF_COMMAND_2:
9794 if (plci_nl_busy (plci))
9796 plci->internal_command = DTMF_COMMAND_2;
9797 return;
9799 plci->internal_command = DTMF_COMMAND_3;
9800 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9801 return;
9802 case DTMF_COMMAND_3:
9803 if ((Rc != OK) && (Rc != OK_FC))
9805 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9806 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9807 Info = _FACILITY_NOT_SUPPORTED;
9808 break;
9811 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9813 plci->dtmf_rec_active |= mask;
9814 break;
9816 break;
9819 case DTMF_LISTEN_TONE_STOP:
9820 mask <<= 1;
9821 case DTMF_LISTEN_MF_STOP:
9822 mask <<= 1;
9824 case DTMF_LISTEN_STOP:
9825 switch (internal_command)
9827 default:
9828 plci->dtmf_rec_active &= ~mask;
9829 if (plci->dtmf_rec_active)
9830 break;
9832 case DTMF_COMMAND_1:
9833 if (plci->dtmf_rec_active)
9835 if (plci_nl_busy (plci))
9837 plci->internal_command = DTMF_COMMAND_1;
9838 return;
9840 plci->dtmf_rec_active &= ~mask;
9841 plci->internal_command = DTMF_COMMAND_2;
9842 dtmf_enable_receiver (plci, false);
9843 return;
9845 Rc = OK;
9846 case DTMF_COMMAND_2:
9847 if ((Rc != OK) && (Rc != OK_FC))
9849 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9850 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9851 Info = _FACILITY_NOT_SUPPORTED;
9852 break;
9855 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9856 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9857 case DTMF_COMMAND_3:
9858 if (adjust_b_process (Id, plci, Rc) != GOOD)
9860 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9861 UnMapId (Id), (char *)(FILE_), __LINE__));
9862 Info = _FACILITY_NOT_SUPPORTED;
9863 break;
9865 if (plci->internal_command)
9866 return;
9867 break;
9869 break;
9872 case DTMF_SEND_TONE:
9873 mask <<= 1;
9874 case DTMF_SEND_MF:
9875 mask <<= 1;
9877 case DTMF_DIGITS_SEND:
9878 switch (internal_command)
9880 default:
9881 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9882 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9883 DTMF_COMMAND_1);
9884 case DTMF_COMMAND_1:
9885 if (adjust_b_process (Id, plci, Rc) != GOOD)
9887 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9888 UnMapId (Id), (char *)(FILE_), __LINE__));
9889 Info = _FACILITY_NOT_SUPPORTED;
9890 break;
9892 if (plci->internal_command)
9893 return;
9894 case DTMF_COMMAND_2:
9895 if (plci_nl_busy (plci))
9897 plci->internal_command = DTMF_COMMAND_2;
9898 return;
9900 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9901 plci->internal_command = DTMF_COMMAND_3;
9902 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9903 return;
9904 case DTMF_COMMAND_3:
9905 if ((Rc != OK) && (Rc != OK_FC))
9907 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9908 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9909 if (plci->dtmf_send_requests != 0)
9910 (plci->dtmf_send_requests)--;
9911 Info = _FACILITY_NOT_SUPPORTED;
9912 break;
9914 return;
9916 break;
9918 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9919 "wws", Info, SELECTOR_DTMF, result);
9923 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9925 word Info;
9926 word i, j;
9927 byte mask;
9928 API_PARSE dtmf_parms[5];
9929 byte result[40];
9931 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9932 UnMapId (Id), (char *)(FILE_), __LINE__));
9934 Info = GOOD;
9935 result[0] = 2;
9936 PUT_WORD (&result[1], DTMF_SUCCESS);
9937 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9939 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9940 UnMapId (Id), (char *)(FILE_), __LINE__));
9941 Info = _FACILITY_NOT_SUPPORTED;
9943 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9945 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9946 UnMapId (Id), (char *)(FILE_), __LINE__));
9947 Info = _WRONG_MESSAGE_FORMAT;
9950 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9951 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9953 if (!((a->requested_options_table[appl->Id-1])
9954 & (1L << PRIVATE_DTMF_TONE)))
9956 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9957 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9958 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9960 else
9962 for (i = 0; i < 32; i++)
9963 result[4 + i] = 0;
9964 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9966 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9968 if (dtmf_digit_map[i].listen_mask != 0)
9969 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9972 else
9974 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9976 if (dtmf_digit_map[i].send_mask != 0)
9977 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9980 result[0] = 3 + 32;
9981 result[3] = 32;
9985 else if (plci == NULL)
9987 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9988 UnMapId (Id), (char *)(FILE_), __LINE__));
9989 Info = _WRONG_IDENTIFIER;
9991 else
9993 if (!plci->State
9994 || !plci->NL.Id || plci->nl_remove_id)
9996 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9997 UnMapId (Id), (char *)(FILE_), __LINE__));
9998 Info = _WRONG_STATE;
10000 else
10002 plci->command = 0;
10003 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
10004 mask = 0x01;
10005 switch (plci->dtmf_cmd)
10008 case DTMF_LISTEN_TONE_START:
10009 case DTMF_LISTEN_TONE_STOP:
10010 mask <<= 1;
10011 case DTMF_LISTEN_MF_START:
10012 case DTMF_LISTEN_MF_STOP:
10013 mask <<= 1;
10014 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10015 & (1L << PRIVATE_DTMF_TONE)))
10017 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10018 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10019 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10020 break;
10023 case DTMF_LISTEN_START:
10024 case DTMF_LISTEN_STOP:
10025 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10026 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10028 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10029 UnMapId (Id), (char *)(FILE_), __LINE__));
10030 Info = _FACILITY_NOT_SUPPORTED;
10031 break;
10033 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10035 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10037 plci->dtmf_rec_pulse_ms = 0;
10038 plci->dtmf_rec_pause_ms = 0;
10040 else
10042 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10043 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10046 start_internal_command (Id, plci, dtmf_command);
10047 return (false);
10050 case DTMF_SEND_TONE:
10051 mask <<= 1;
10052 case DTMF_SEND_MF:
10053 mask <<= 1;
10054 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10055 & (1L << PRIVATE_DTMF_TONE)))
10057 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10058 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10059 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10060 break;
10063 case DTMF_DIGITS_SEND:
10064 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10066 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10067 UnMapId (Id), (char *)(FILE_), __LINE__));
10068 Info = _WRONG_MESSAGE_FORMAT;
10069 break;
10071 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10073 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10074 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10076 i = 0;
10077 j = 0;
10078 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10080 j = 0;
10081 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10082 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10083 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10085 j++;
10087 i++;
10089 if (j == DTMF_DIGIT_MAP_ENTRIES)
10091 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10092 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10093 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10094 break;
10096 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10098 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10099 UnMapId (Id), (char *)(FILE_), __LINE__));
10100 Info = _WRONG_STATE;
10101 break;
10103 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10104 start_internal_command (Id, plci, dtmf_command);
10105 return (false);
10107 default:
10108 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10109 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10110 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10114 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10115 "wws", Info, SELECTOR_DTMF, result);
10116 return (false);
10120 static void dtmf_confirmation (dword Id, PLCI *plci)
10122 word Info;
10123 word i;
10124 byte result[4];
10126 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10127 UnMapId (Id), (char *)(FILE_), __LINE__));
10129 Info = GOOD;
10130 result[0] = 2;
10131 PUT_WORD (&result[1], DTMF_SUCCESS);
10132 if (plci->dtmf_send_requests != 0)
10134 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10135 "wws", GOOD, SELECTOR_DTMF, result);
10136 (plci->dtmf_send_requests)--;
10137 for (i = 0; i < plci->dtmf_send_requests; i++)
10138 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10143 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10145 word i, j, n;
10147 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10148 UnMapId (Id), (char *)(FILE_), __LINE__));
10150 n = 0;
10151 for (i = 1; i < length; i++)
10153 j = 0;
10154 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10155 && ((msg[i] != dtmf_digit_map[j].code)
10156 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10158 j++;
10160 if (j < DTMF_DIGIT_MAP_ENTRIES)
10163 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10164 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10165 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10167 if (n + 1 == i)
10169 for (i = length; i > n + 1; i--)
10170 msg[i] = msg[i - 1];
10171 length++;
10172 i++;
10174 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10176 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10178 msg[++n] = dtmf_digit_map[j].character;
10181 if (n != 0)
10183 msg[0] = (byte) n;
10184 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10189 /*------------------------------------------------------------------*/
10190 /* DTMF parameters */
10191 /*------------------------------------------------------------------*/
10193 static void dtmf_parameter_write (PLCI *plci)
10195 word i;
10196 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10198 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10199 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10200 (char *)(FILE_), __LINE__));
10202 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10203 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10204 for (i = 0; i < plci->dtmf_parameter_length; i++)
10205 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10206 add_p (plci, FTY, parameter_buffer);
10207 sig_req (plci, TEL_CTRL, 0);
10208 send_req (plci);
10212 static void dtmf_parameter_clear_config (PLCI *plci)
10215 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10216 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10217 (char *)(FILE_), __LINE__));
10219 plci->dtmf_parameter_length = 0;
10223 static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10226 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10227 UnMapId (Id), (char *)(FILE_), __LINE__));
10232 static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10235 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10236 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10238 return (GOOD);
10242 static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10244 word Info;
10246 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10247 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10249 Info = GOOD;
10250 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10251 && (plci->dtmf_parameter_length != 0))
10253 switch (plci->adjust_b_state)
10255 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10256 plci->internal_command = plci->adjust_b_command;
10257 if (plci->sig_req)
10259 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10260 break;
10262 dtmf_parameter_write (plci);
10263 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10264 break;
10265 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10266 if ((Rc != OK) && (Rc != OK_FC))
10268 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10269 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10270 Info = _WRONG_STATE;
10271 break;
10273 break;
10276 return (Info);
10280 /*------------------------------------------------------------------*/
10281 /* Line interconnect facilities */
10282 /*------------------------------------------------------------------*/
10285 LI_CONFIG *li_config_table;
10286 word li_total_channels;
10289 /*------------------------------------------------------------------*/
10290 /* translate a CHI information element to a channel number */
10291 /* returns 0xff - any channel */
10292 /* 0xfe - chi wrong coding */
10293 /* 0xfd - D-channel */
10294 /* 0x00 - no channel */
10295 /* else channel number / PRI: timeslot */
10296 /* if channels is provided we accept more than one channel. */
10297 /*------------------------------------------------------------------*/
10299 static byte chi_to_channel (byte *chi, dword *pchannelmap)
10301 int p;
10302 int i;
10303 dword map;
10304 byte excl;
10305 byte ofs;
10306 byte ch;
10308 if (pchannelmap) *pchannelmap = 0;
10309 if(!chi[0]) return 0xff;
10310 excl = 0;
10312 if(chi[1] & 0x20) {
10313 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10314 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10315 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10316 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10317 if(chi[1] &0x08) excl = 0x40;
10319 /* int. id present */
10320 if(chi[1] &0x40) {
10321 p=i+1;
10322 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10323 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10326 /* coding standard, Number/Map, Channel Type */
10327 p=i+1;
10328 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10329 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10330 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10332 /* Number/Map */
10333 if(chi[p] &0x10) {
10335 /* map */
10336 if((chi[0]-p)==4) ofs = 0;
10337 else if((chi[0]-p)==3) ofs = 1;
10338 else return 0xfe;
10339 ch = 0;
10340 map = 0;
10341 for(i=0; i<4 && p<chi[0]; i++) {
10342 p++;
10343 ch += 8;
10344 map <<= 8;
10345 if(chi[p]) {
10346 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10347 map |= chi[p];
10350 ch += ofs;
10351 map <<= ofs;
10353 else {
10355 /* number */
10356 p=i+1;
10357 ch = chi[p] &0x3f;
10358 if(pchannelmap) {
10359 if((byte)(chi[0]-p)>30) return 0xfe;
10360 map = 0;
10361 for(i=p; i<=chi[0]; i++) {
10362 if ((chi[i] &0x7f) > 31) return 0xfe;
10363 map |= (1L << (chi[i] &0x7f));
10366 else {
10367 if(p!=chi[0]) return 0xfe;
10368 if (ch > 31) return 0xfe;
10369 map = (1L << ch);
10371 if(chi[p] &0x40) return 0xfe;
10373 if (pchannelmap) *pchannelmap = map;
10374 else if (map != ((dword)(1L << ch))) return 0xfe;
10375 return (byte)(excl | ch);
10377 else { /* not PRI */
10378 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10379 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10380 if(chi[1] &0x08) excl = 0x40;
10382 switch(chi[1] |0x98) {
10383 case 0x98: return 0;
10384 case 0x99:
10385 if (pchannelmap) *pchannelmap = 2;
10386 return excl |1;
10387 case 0x9a:
10388 if (pchannelmap) *pchannelmap = 4;
10389 return excl |2;
10390 case 0x9b: return 0xff;
10391 case 0x9c: return 0xfd; /* d-ch */
10392 default: return 0xfe;
10398 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10400 DIVA_CAPI_ADAPTER *a;
10401 PLCI *splci;
10402 byte old_id;
10404 a = plci->adapter;
10405 old_id = plci->li_bchannel_id;
10406 if (a->li_pri)
10408 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10409 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10410 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10411 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10412 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10414 else
10416 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10418 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10419 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10420 plci->li_bchannel_id = bchannel_id & 0x03;
10421 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10423 splci = a->AdvSignalPLCI;
10424 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10426 if ((splci->li_bchannel_id != 0)
10427 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10429 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10431 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10432 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10433 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10434 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10435 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10438 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10439 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10442 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10443 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10445 mixer_clear_config (plci);
10447 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10448 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10449 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10453 static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10455 DIVA_CAPI_ADAPTER *a;
10456 PLCI *splci;
10457 byte ch, old_id;
10459 a = plci->adapter;
10460 old_id = plci->li_bchannel_id;
10461 ch = chi_to_channel (chi, NULL);
10462 if (!(ch & 0x80))
10464 if (a->li_pri)
10466 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10467 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10468 plci->li_bchannel_id = (ch & 0x1f) + 1;
10469 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10470 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10472 else
10474 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10476 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10477 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10478 plci->li_bchannel_id = ch & 0x1f;
10479 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10481 splci = a->AdvSignalPLCI;
10482 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10484 if ((splci->li_bchannel_id != 0)
10485 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10487 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10489 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10490 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10491 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10492 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10493 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10496 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10497 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10501 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10502 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10504 mixer_clear_config (plci);
10506 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10507 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10508 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10512 #define MIXER_MAX_DUMP_CHANNELS 34
10514 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10516 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10517 word n, i, j;
10518 char *p;
10519 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10521 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10522 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10524 for (i = 0; i < li_total_channels; i++)
10526 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10527 if (li_config_table[i].chflags != 0)
10528 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10529 else
10531 for (j = 0; j < li_total_channels; j++)
10533 if (((li_config_table[i].flag_table[j]) != 0)
10534 || ((li_config_table[j].flag_table[i]) != 0))
10536 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10538 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10539 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10541 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10546 for (i = 0; i < li_total_channels; i++)
10548 for (j = 0; j < li_total_channels; j++)
10550 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10551 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10552 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10555 for (n = 0; n < li_total_channels; n++)
10557 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10559 for (i = 0; i < li_total_channels; i++)
10561 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10563 for (j = 0; j < li_total_channels; j++)
10565 li_config_table[i].coef_table[j] |=
10566 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10572 for (i = 0; i < li_total_channels; i++)
10574 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10576 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10577 for (j = 0; j < li_total_channels; j++)
10579 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10580 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10582 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10583 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10586 for (i = 0; i < li_total_channels; i++)
10588 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10590 for (j = 0; j < li_total_channels; j++)
10592 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10593 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10594 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10595 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10596 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10597 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10598 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10599 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10601 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10603 for (j = 0; j < li_total_channels; j++)
10605 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10607 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10608 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10609 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10613 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10615 for (j = 0; j < li_total_channels; j++)
10617 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10618 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10621 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10623 for (j = 0; j < li_total_channels; j++)
10625 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10627 for (n = 0; n < li_total_channels; n++)
10629 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10631 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10632 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10634 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10635 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10636 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10638 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10639 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10647 for (i = 0; i < li_total_channels; i++)
10649 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10651 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10652 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10653 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10654 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10655 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10656 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10657 for (j = 0; j < li_total_channels; j++)
10659 if ((li_config_table[i].flag_table[j] &
10660 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10661 || (li_config_table[j].flag_table[i] &
10662 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10664 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10666 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10667 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10668 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10669 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10671 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10673 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10674 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10678 for (i = 0; i < li_total_channels; i++)
10680 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10682 j = 0;
10683 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10684 j++;
10685 if (j < li_total_channels)
10687 for (j = 0; j < li_total_channels; j++)
10689 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10690 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10691 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10696 n = li_total_channels;
10697 if (n > MIXER_MAX_DUMP_CHANNELS)
10698 n = MIXER_MAX_DUMP_CHANNELS;
10699 p = hex_line;
10700 for (j = 0; j < n; j++)
10702 if ((j & 0x7) == 0)
10703 *(p++) = ' ';
10704 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10705 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10707 *p = '\0';
10708 dbug (1, dprintf ("[%06lx] CURRENT %s",
10709 (dword)(UnMapController (a->Id)), (char *) hex_line));
10710 p = hex_line;
10711 for (j = 0; j < n; j++)
10713 if ((j & 0x7) == 0)
10714 *(p++) = ' ';
10715 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10716 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10718 *p = '\0';
10719 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10720 (dword)(UnMapController (a->Id)), (char *) hex_line));
10721 p = hex_line;
10722 for (j = 0; j < n; j++)
10724 if ((j & 0x7) == 0)
10725 *(p++) = ' ';
10726 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10727 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10729 *p = '\0';
10730 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10731 (dword)(UnMapController (a->Id)), (char *) hex_line));
10732 for (i = 0; i < n; i++)
10734 p = hex_line;
10735 for (j = 0; j < n; j++)
10737 if ((j & 0x7) == 0)
10738 *(p++) = ' ';
10739 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10740 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10742 *p = '\0';
10743 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10744 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10746 for (i = 0; i < n; i++)
10748 p = hex_line;
10749 for (j = 0; j < n; j++)
10751 if ((j & 0x7) == 0)
10752 *(p++) = ' ';
10753 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10754 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10756 *p = '\0';
10757 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10758 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10763 static struct
10765 byte mask;
10766 byte line_flags;
10767 } mixer_write_prog_pri[] =
10769 { LI_COEF_CH_CH, 0 },
10770 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10771 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10772 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10775 static struct
10777 byte from_ch;
10778 byte to_ch;
10779 byte mask;
10780 byte xconnect_override;
10781 } mixer_write_prog_bri[] =
10783 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10784 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10785 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10786 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10787 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10788 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10789 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10790 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10791 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10792 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10793 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10794 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10795 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10796 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10797 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10798 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10799 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10800 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10801 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10802 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10803 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10804 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10805 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10806 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10807 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10808 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10809 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10810 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10811 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10812 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10813 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10814 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10815 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10816 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10817 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10818 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10821 static byte mixer_swapped_index_bri[] =
10823 18, /* B to B */
10824 19, /* Alt B to B */
10825 20, /* PC to B */
10826 21, /* Alt PC to B */
10827 22, /* IC to B */
10828 23, /* Alt IC to B */
10829 24, /* B to PC */
10830 25, /* Alt B to PC */
10831 26, /* PC to PC */
10832 27, /* Alt PC to PC */
10833 28, /* IC to PC */
10834 29, /* Alt IC to PC */
10835 30, /* B to IC */
10836 31, /* Alt B to IC */
10837 32, /* PC to IC */
10838 33, /* Alt PC to IC */
10839 34, /* IC to IC */
10840 35, /* Alt IC to IC */
10841 0, /* Alt B to Alt B */
10842 1, /* B to Alt B */
10843 2, /* Alt PC to Alt B */
10844 3, /* PC to Alt B */
10845 4, /* Alt IC to Alt B */
10846 5, /* IC to Alt B */
10847 6, /* Alt B to Alt PC */
10848 7, /* B to Alt PC */
10849 8, /* Alt PC to Alt PC */
10850 9, /* PC to Alt PC */
10851 10, /* Alt IC to Alt PC */
10852 11, /* IC to Alt PC */
10853 12, /* Alt B to Alt IC */
10854 13, /* B to Alt IC */
10855 14, /* Alt PC to Alt IC */
10856 15, /* PC to Alt IC */
10857 16, /* Alt IC to Alt IC */
10858 17 /* IC to Alt IC */
10861 static struct
10863 byte mask;
10864 byte from_pc;
10865 byte to_pc;
10866 } xconnect_write_prog[] =
10868 { LI_COEF_CH_CH, false, false },
10869 { LI_COEF_CH_PC, false, true },
10870 { LI_COEF_PC_CH, true, false },
10871 { LI_COEF_PC_PC, true, true }
10875 static void xconnect_query_addresses (PLCI *plci)
10877 DIVA_CAPI_ADAPTER *a;
10878 word w, ch;
10879 byte *p;
10881 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10882 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10883 (char *)(FILE_), __LINE__));
10885 a = plci->adapter;
10886 if (a->li_pri && ((plci->li_bchannel_id == 0)
10887 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10889 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10890 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10891 (char *)(FILE_), __LINE__));
10892 return;
10894 p = plci->internal_req_buffer;
10895 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10896 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10897 w = ch;
10898 *(p++) = (byte) w;
10899 *(p++) = (byte)(w >> 8);
10900 w = ch | XCONNECT_CHANNEL_PORT_PC;
10901 *(p++) = (byte) w;
10902 *(p++) = (byte)(w >> 8);
10903 plci->NData[0].P = plci->internal_req_buffer;
10904 plci->NData[0].PLength = p - plci->internal_req_buffer;
10905 plci->NL.X = plci->NData;
10906 plci->NL.ReqCh = 0;
10907 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10908 plci->adapter->request (&plci->NL);
10912 static void xconnect_write_coefs (PLCI *plci, word internal_command)
10915 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10916 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10917 (char *)(FILE_), __LINE__, internal_command));
10919 plci->li_write_command = internal_command;
10920 plci->li_write_channel = 0;
10924 static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10926 DIVA_CAPI_ADAPTER *a;
10927 word w, n, i, j, r, s, to_ch;
10928 dword d;
10929 byte *p;
10930 struct xconnect_transfer_address_s *transfer_address;
10931 byte ch_map[MIXER_CHANNELS_BRI];
10933 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10934 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10936 a = plci->adapter;
10937 if ((plci->li_bchannel_id == 0)
10938 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10940 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10941 UnMapId (Id), (char *)(FILE_), __LINE__));
10942 return (true);
10944 i = a->li_base + (plci->li_bchannel_id - 1);
10945 j = plci->li_write_channel;
10946 p = plci->internal_req_buffer;
10947 if (j != 0)
10949 if ((Rc != OK) && (Rc != OK_FC))
10951 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10952 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10953 return (false);
10956 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10958 r = 0;
10959 s = 0;
10960 if (j < li_total_channels)
10962 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10964 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10965 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10966 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10967 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10969 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10970 while ((j < li_total_channels)
10971 && ((r == 0)
10972 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10973 || (!li_config_table[j].adapter->li_pri
10974 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10975 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10976 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10977 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10978 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10979 || ((li_config_table[j].adapter->li_base != a->li_base)
10980 && !(r & s &
10981 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10982 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10983 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10984 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10986 j++;
10987 if (j < li_total_channels)
10988 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10991 if (j < li_total_channels)
10993 plci->internal_command = plci->li_write_command;
10994 if (plci_nl_busy (plci))
10995 return (true);
10996 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10997 *(p++) = UDATA_REQUEST_XCONNECT_TO;
11000 if (li_config_table[j].adapter->li_base != a->li_base)
11002 r &= s &
11003 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11004 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11005 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11006 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11008 n = 0;
11011 if (r & xconnect_write_prog[n].mask)
11013 if (xconnect_write_prog[n].from_pc)
11014 transfer_address = &(li_config_table[j].send_pc);
11015 else
11016 transfer_address = &(li_config_table[j].send_b);
11017 d = transfer_address->card_address.low;
11018 *(p++) = (byte) d;
11019 *(p++) = (byte)(d >> 8);
11020 *(p++) = (byte)(d >> 16);
11021 *(p++) = (byte)(d >> 24);
11022 d = transfer_address->card_address.high;
11023 *(p++) = (byte) d;
11024 *(p++) = (byte)(d >> 8);
11025 *(p++) = (byte)(d >> 16);
11026 *(p++) = (byte)(d >> 24);
11027 d = transfer_address->offset;
11028 *(p++) = (byte) d;
11029 *(p++) = (byte)(d >> 8);
11030 *(p++) = (byte)(d >> 16);
11031 *(p++) = (byte)(d >> 24);
11032 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11033 *(p++) = (byte) w;
11034 *(p++) = (byte)(w >> 8);
11035 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11036 (li_config_table[i].adapter->u_law ?
11037 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11038 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11039 *(p++) = (byte) w;
11040 *(p++) = (byte) 0;
11041 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11043 n++;
11044 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11045 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11046 if (n == ARRAY_SIZE(xconnect_write_prog))
11050 j++;
11051 if (j < li_total_channels)
11052 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11053 } while ((j < li_total_channels)
11054 && ((r == 0)
11055 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11056 || (!li_config_table[j].adapter->li_pri
11057 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11058 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11059 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11060 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11061 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11062 || ((li_config_table[j].adapter->li_base != a->li_base)
11063 && !(r & s &
11064 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11065 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11066 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11067 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11069 } while ((j < li_total_channels)
11070 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11072 else if (j == li_total_channels)
11074 plci->internal_command = plci->li_write_command;
11075 if (plci_nl_busy (plci))
11076 return (true);
11077 if (a->li_pri)
11079 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11080 w = 0;
11081 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11082 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11083 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11084 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11085 *(p++) = (byte) w;
11086 *(p++) = (byte)(w >> 8);
11088 else
11090 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11091 w = 0;
11092 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11093 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11095 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11097 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11098 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11099 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11100 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11101 *(p++) = (byte) w;
11102 *(p++) = (byte)(w >> 8);
11103 for (j = 0; j < sizeof(ch_map); j += 2)
11105 if (plci->li_bchannel_id == 2)
11107 ch_map[j] = (byte)(j+1);
11108 ch_map[j+1] = (byte) j;
11110 else
11112 ch_map[j] = (byte) j;
11113 ch_map[j+1] = (byte)(j+1);
11116 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11118 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11119 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11120 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11122 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11123 mixer_write_prog_bri[n].xconnect_override :
11124 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11125 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11127 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11128 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11131 else
11133 *p = 0x00;
11134 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11136 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11137 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11138 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11141 p++;
11144 j = li_total_channels + 1;
11147 else
11149 if (j <= li_total_channels)
11151 plci->internal_command = plci->li_write_command;
11152 if (plci_nl_busy (plci))
11153 return (true);
11154 if (j < a->li_base)
11155 j = a->li_base;
11156 if (a->li_pri)
11158 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11159 w = 0;
11160 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11161 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11162 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11163 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11164 *(p++) = (byte) w;
11165 *(p++) = (byte)(w >> 8);
11166 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11168 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11169 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11171 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11172 if (w & mixer_write_prog_pri[n].mask)
11174 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11175 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11177 else
11178 *(p++) = 0x00;
11180 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11181 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11183 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11184 if (w & mixer_write_prog_pri[n].mask)
11186 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11187 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11189 else
11190 *(p++) = 0x00;
11194 else
11196 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11197 w = 0;
11198 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11199 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11201 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11203 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11204 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11205 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11206 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11207 *(p++) = (byte) w;
11208 *(p++) = (byte)(w >> 8);
11209 for (j = 0; j < sizeof(ch_map); j += 2)
11211 if (plci->li_bchannel_id == 2)
11213 ch_map[j] = (byte)(j+1);
11214 ch_map[j+1] = (byte) j;
11216 else
11218 ch_map[j] = (byte) j;
11219 ch_map[j+1] = (byte)(j+1);
11222 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11224 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11225 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11226 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11228 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11229 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11230 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11232 else
11234 *p = 0x00;
11235 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11237 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11238 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11239 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11242 p++;
11245 j = li_total_channels + 1;
11248 plci->li_write_channel = j;
11249 if (p != plci->internal_req_buffer)
11251 plci->NData[0].P = plci->internal_req_buffer;
11252 plci->NData[0].PLength = p - plci->internal_req_buffer;
11253 plci->NL.X = plci->NData;
11254 plci->NL.ReqCh = 0;
11255 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11256 plci->adapter->request (&plci->NL);
11258 return (true);
11262 static void mixer_notify_update (PLCI *plci, byte others)
11264 DIVA_CAPI_ADAPTER *a;
11265 word i, w;
11266 PLCI *notify_plci;
11267 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11269 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11270 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11271 (char *)(FILE_), __LINE__, others));
11273 a = plci->adapter;
11274 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11276 if (others)
11277 plci->li_notify_update = true;
11278 i = 0;
11281 notify_plci = NULL;
11282 if (others)
11284 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11285 i++;
11286 if (i < li_total_channels)
11287 notify_plci = li_config_table[i++].plci;
11289 else
11291 if ((plci->li_bchannel_id != 0)
11292 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11294 notify_plci = plci;
11297 if ((notify_plci != NULL)
11298 && !notify_plci->li_notify_update
11299 && (notify_plci->appl != NULL)
11300 && (notify_plci->State)
11301 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11303 notify_plci->li_notify_update = true;
11304 ((CAPI_MSG *) msg)->header.length = 18;
11305 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11306 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11307 ((CAPI_MSG *) msg)->header.number = 0;
11308 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11309 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11310 ((CAPI_MSG *) msg)->header.ncci = 0;
11311 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11312 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11313 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11314 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11315 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11316 if (w != _QUEUE_FULL)
11318 if (w != 0)
11320 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11321 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11322 (char *)(FILE_), __LINE__,
11323 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11325 notify_plci->li_notify_update = false;
11328 } while (others && (notify_plci != NULL));
11329 if (others)
11330 plci->li_notify_update = false;
11335 static void mixer_clear_config (PLCI *plci)
11337 DIVA_CAPI_ADAPTER *a;
11338 word i, j;
11340 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11341 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11342 (char *)(FILE_), __LINE__));
11344 plci->li_notify_update = false;
11345 plci->li_plci_b_write_pos = 0;
11346 plci->li_plci_b_read_pos = 0;
11347 plci->li_plci_b_req_pos = 0;
11348 a = plci->adapter;
11349 if ((plci->li_bchannel_id != 0)
11350 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11352 i = a->li_base + (plci->li_bchannel_id - 1);
11353 li_config_table[i].curchnl = 0;
11354 li_config_table[i].channel = 0;
11355 li_config_table[i].chflags = 0;
11356 for (j = 0; j < li_total_channels; j++)
11358 li_config_table[j].flag_table[i] = 0;
11359 li_config_table[i].flag_table[j] = 0;
11360 li_config_table[i].coef_table[j] = 0;
11361 li_config_table[j].coef_table[i] = 0;
11363 if (!a->li_pri)
11365 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11366 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11368 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11369 li_config_table[i].curchnl = 0;
11370 li_config_table[i].channel = 0;
11371 li_config_table[i].chflags = 0;
11372 for (j = 0; j < li_total_channels; j++)
11374 li_config_table[i].flag_table[j] = 0;
11375 li_config_table[j].flag_table[i] = 0;
11376 li_config_table[i].coef_table[j] = 0;
11377 li_config_table[j].coef_table[i] = 0;
11379 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11381 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11382 li_config_table[i].curchnl = 0;
11383 li_config_table[i].channel = 0;
11384 li_config_table[i].chflags = 0;
11385 for (j = 0; j < li_total_channels; j++)
11387 li_config_table[i].flag_table[j] = 0;
11388 li_config_table[j].flag_table[i] = 0;
11389 li_config_table[i].coef_table[j] = 0;
11390 li_config_table[j].coef_table[i] = 0;
11399 static void mixer_prepare_switch (dword Id, PLCI *plci)
11402 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11403 UnMapId (Id), (char *)(FILE_), __LINE__));
11407 mixer_indication_coefs_set (Id, plci);
11408 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11412 static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11414 DIVA_CAPI_ADAPTER *a;
11415 word i, j;
11417 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11418 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11420 a = plci->adapter;
11421 if ((plci->li_bchannel_id != 0)
11422 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11424 i = a->li_base + (plci->li_bchannel_id - 1);
11425 for (j = 0; j < li_total_channels; j++)
11427 li_config_table[i].coef_table[j] &= 0xf;
11428 li_config_table[j].coef_table[i] &= 0xf;
11430 if (!a->li_pri)
11431 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11433 return (GOOD);
11437 static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11439 DIVA_CAPI_ADAPTER *a;
11440 word Info;
11442 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11443 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11445 Info = GOOD;
11446 a = plci->adapter;
11447 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11448 && (plci->li_bchannel_id != 0)
11449 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11451 switch (plci->adjust_b_state)
11453 case ADJUST_B_RESTORE_MIXER_1:
11454 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11456 plci->internal_command = plci->adjust_b_command;
11457 if (plci_nl_busy (plci))
11459 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11460 break;
11462 xconnect_query_addresses (plci);
11463 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11464 break;
11466 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11467 Rc = OK;
11468 case ADJUST_B_RESTORE_MIXER_2:
11469 case ADJUST_B_RESTORE_MIXER_3:
11470 case ADJUST_B_RESTORE_MIXER_4:
11471 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11473 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11474 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11475 Info = _WRONG_STATE;
11476 break;
11478 if (Rc == OK)
11480 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11481 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11482 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11483 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11485 else if (Rc == 0)
11487 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11488 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11489 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11490 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11492 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11494 plci->internal_command = plci->adjust_b_command;
11495 break;
11497 case ADJUST_B_RESTORE_MIXER_5:
11498 xconnect_write_coefs (plci, plci->adjust_b_command);
11499 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11500 Rc = OK;
11501 case ADJUST_B_RESTORE_MIXER_6:
11502 if (!xconnect_write_coefs_process (Id, plci, Rc))
11504 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11505 UnMapId (Id), (char *)(FILE_), __LINE__));
11506 Info = _FACILITY_NOT_SUPPORTED;
11507 break;
11509 if (plci->internal_command)
11510 break;
11511 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11512 case ADJUST_B_RESTORE_MIXER_7:
11513 break;
11516 return (Info);
11520 static void mixer_command (dword Id, PLCI *plci, byte Rc)
11522 DIVA_CAPI_ADAPTER *a;
11523 word i, internal_command, Info;
11525 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11526 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11527 plci->li_cmd));
11529 Info = GOOD;
11530 a = plci->adapter;
11531 internal_command = plci->internal_command;
11532 plci->internal_command = 0;
11533 switch (plci->li_cmd)
11535 case LI_REQ_CONNECT:
11536 case LI_REQ_DISCONNECT:
11537 case LI_REQ_SILENT_UPDATE:
11538 switch (internal_command)
11540 default:
11541 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11543 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11544 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11546 case MIXER_COMMAND_1:
11547 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11549 if (adjust_b_process (Id, plci, Rc) != GOOD)
11551 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11552 UnMapId (Id), (char *)(FILE_), __LINE__));
11553 Info = _FACILITY_NOT_SUPPORTED;
11554 break;
11556 if (plci->internal_command)
11557 return;
11559 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11560 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11561 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11562 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11563 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11565 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11567 else
11571 mixer_indication_coefs_set (Id, plci);
11572 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11574 case MIXER_COMMAND_2:
11575 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11576 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11577 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11578 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11580 if (!xconnect_write_coefs_process (Id, plci, Rc))
11582 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11583 UnMapId (Id), (char *)(FILE_), __LINE__));
11584 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11588 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11589 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11590 i = (plci->li_plci_b_write_pos == 0) ?
11591 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11592 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11593 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11595 Info = _FACILITY_NOT_SUPPORTED;
11596 break;
11598 if (plci->internal_command)
11599 return;
11601 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11603 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11604 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11606 case MIXER_COMMAND_3:
11607 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11609 if (adjust_b_process (Id, plci, Rc) != GOOD)
11611 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11612 UnMapId (Id), (char *)(FILE_), __LINE__));
11613 Info = _FACILITY_NOT_SUPPORTED;
11614 break;
11616 if (plci->internal_command)
11617 return;
11619 break;
11621 break;
11623 if ((plci->li_bchannel_id == 0)
11624 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11626 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11627 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11629 else
11631 i = a->li_base + (plci->li_bchannel_id - 1);
11632 li_config_table[i].curchnl = plci->li_channel_bits;
11633 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11635 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11636 li_config_table[i].curchnl = plci->li_channel_bits;
11637 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11639 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11640 li_config_table[i].curchnl = plci->li_channel_bits;
11647 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11648 dword plci_b_id, byte connect, dword li_flags)
11650 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11651 PLCI *plci_b;
11652 DIVA_CAPI_ADAPTER *a_b;
11654 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11655 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11656 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11657 if (!a->li_pri && (plci->tel == ADV_VOICE)
11658 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11660 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11661 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11662 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11664 else
11666 ch_a_v = ch_a;
11667 ch_a_s = ch_a;
11669 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11670 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11671 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11673 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11674 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11675 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11677 else
11679 ch_b_v = ch_b;
11680 ch_b_s = ch_b;
11682 if (connect)
11684 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11685 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11686 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11687 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11689 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11690 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11691 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11692 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11693 if (ch_a_v == ch_b_v)
11695 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11696 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11698 else
11700 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11702 for (i = 0; i < li_total_channels; i++)
11704 if (i != ch_a_v)
11705 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11708 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11710 for (i = 0; i < li_total_channels; i++)
11712 if (i != ch_a_s)
11713 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11716 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11718 for (i = 0; i < li_total_channels; i++)
11720 if (i != ch_a_v)
11721 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11724 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11726 for (i = 0; i < li_total_channels; i++)
11728 if (i != ch_a_s)
11729 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11733 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11735 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11736 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11737 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11738 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11740 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11742 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11743 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11744 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11745 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11747 if (li_flags & LI_FLAG_MONITOR_A)
11749 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11750 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11752 if (li_flags & LI_FLAG_MONITOR_B)
11754 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11755 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11757 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11759 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11760 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11762 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11764 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11765 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11767 if (li_flags & LI_FLAG_MIX_A)
11769 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11770 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11772 if (li_flags & LI_FLAG_MIX_B)
11774 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11775 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11777 if (ch_a_v != ch_a_s)
11779 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11780 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11782 if (ch_b_v != ch_b_s)
11784 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11785 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11790 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11791 dword plci_b_id, byte connect, dword li_flags)
11793 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11794 PLCI *plci_b;
11795 DIVA_CAPI_ADAPTER *a_b;
11797 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11798 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11799 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11800 if (!a->li_pri && (plci->tel == ADV_VOICE)
11801 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11803 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11804 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11805 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11807 else
11809 ch_a_v = ch_a;
11810 ch_a_s = ch_a;
11812 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11813 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11814 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11816 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11817 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11818 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11820 else
11822 ch_b_v = ch_b;
11823 ch_b_s = ch_b;
11825 if (connect)
11827 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11828 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11829 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11830 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11831 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11832 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11834 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11835 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11836 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11837 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11838 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11839 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11840 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11841 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11842 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11844 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11845 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11846 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11847 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11849 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11851 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11852 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11853 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11854 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856 if (li_flags & LI2_FLAG_MONITOR_B)
11858 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11859 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11861 if (li_flags & LI2_FLAG_MIX_B)
11863 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11864 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11866 if (li_flags & LI2_FLAG_MONITOR_X)
11867 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11868 if (li_flags & LI2_FLAG_MIX_X)
11869 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11870 if (li_flags & LI2_FLAG_LOOP_B)
11872 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11873 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11874 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11875 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11877 if (li_flags & LI2_FLAG_LOOP_PC)
11878 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11879 if (li_flags & LI2_FLAG_LOOP_X)
11880 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11881 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11882 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11883 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11884 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11885 if (ch_a_v != ch_a_s)
11887 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11888 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11890 if (ch_b_v != ch_b_s)
11892 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11893 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11898 static word li_check_main_plci (dword Id, PLCI *plci)
11900 if (plci == NULL)
11902 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11903 UnMapId (Id), (char *)(FILE_), __LINE__));
11904 return (_WRONG_IDENTIFIER);
11906 if (!plci->State
11907 || !plci->NL.Id || plci->nl_remove_id
11908 || (plci->li_bchannel_id == 0))
11910 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11911 UnMapId (Id), (char *)(FILE_), __LINE__));
11912 return (_WRONG_STATE);
11914 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11915 return (GOOD);
11919 static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11920 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11922 byte ctlr_b;
11923 PLCI *plci_b;
11925 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11926 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11928 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11929 UnMapId (Id), (char *)(FILE_), __LINE__));
11930 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11931 return (NULL);
11933 ctlr_b = 0;
11934 if ((plci_b_id & 0x7f) != 0)
11936 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11937 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11938 ctlr_b = 0;
11940 if ((ctlr_b == 0)
11941 || (((plci_b_id >> 8) & 0xff) == 0)
11942 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11944 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11945 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11946 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11947 return (NULL);
11949 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11950 if (!plci_b->State
11951 || !plci_b->NL.Id || plci_b->nl_remove_id
11952 || (plci_b->li_bchannel_id == 0))
11954 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11955 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11956 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11957 return (NULL);
11959 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11960 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11961 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11962 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11963 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11965 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11966 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11967 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11968 return (NULL);
11970 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11971 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11973 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11974 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11975 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11976 return (NULL);
11978 return (plci_b);
11982 static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11983 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11985 byte ctlr_b;
11986 PLCI *plci_b;
11988 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11989 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11991 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11992 UnMapId (Id), (char *)(FILE_), __LINE__));
11993 PUT_WORD (p_result, _WRONG_STATE);
11994 return (NULL);
11996 ctlr_b = 0;
11997 if ((plci_b_id & 0x7f) != 0)
11999 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
12000 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
12001 ctlr_b = 0;
12003 if ((ctlr_b == 0)
12004 || (((plci_b_id >> 8) & 0xff) == 0)
12005 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
12007 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
12008 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12009 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12010 return (NULL);
12012 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12013 if (!plci_b->State
12014 || !plci_b->NL.Id || plci_b->nl_remove_id
12015 || (plci_b->li_bchannel_id == 0)
12016 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12018 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12019 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12020 PUT_WORD (p_result, _WRONG_STATE);
12021 return (NULL);
12023 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12024 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12025 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12026 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12028 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12029 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12030 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12031 return (NULL);
12033 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12034 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12036 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12037 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12038 PUT_WORD (p_result, _WRONG_STATE);
12039 return (NULL);
12041 return (plci_b);
12045 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12047 word Info;
12048 word i;
12049 dword d, li_flags, plci_b_id;
12050 PLCI *plci_b;
12051 API_PARSE li_parms[3];
12052 API_PARSE li_req_parms[3];
12053 API_PARSE li_participant_struct[2];
12054 API_PARSE li_participant_parms[3];
12055 word participant_parms_pos;
12056 byte result_buffer[32];
12057 byte *result;
12058 word result_pos;
12059 word plci_b_write_pos;
12061 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12062 UnMapId (Id), (char *)(FILE_), __LINE__));
12064 Info = GOOD;
12065 result = result_buffer;
12066 result_buffer[0] = 0;
12067 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12069 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12070 UnMapId (Id), (char *)(FILE_), __LINE__));
12071 Info = _FACILITY_NOT_SUPPORTED;
12073 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12075 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12076 UnMapId (Id), (char *)(FILE_), __LINE__));
12077 Info = _WRONG_MESSAGE_FORMAT;
12079 else
12081 result_buffer[0] = 3;
12082 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12083 result_buffer[3] = 0;
12084 switch (GET_WORD (li_parms[0].info))
12086 case LI_GET_SUPPORTED_SERVICES:
12087 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12089 result_buffer[0] = 17;
12090 result_buffer[3] = 14;
12091 PUT_WORD (&result_buffer[4], GOOD);
12092 d = 0;
12093 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12094 d |= LI_CONFERENCING_SUPPORTED;
12095 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12096 d |= LI_MONITORING_SUPPORTED;
12097 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12098 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12099 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12100 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12101 PUT_DWORD (&result_buffer[6], d);
12102 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12104 d = 0;
12105 for (i = 0; i < li_total_channels; i++)
12107 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12108 && (li_config_table[i].adapter->li_pri
12109 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12111 d++;
12115 else
12117 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12119 PUT_DWORD (&result_buffer[10], d / 2);
12120 PUT_DWORD (&result_buffer[14], d);
12122 else
12124 result_buffer[0] = 25;
12125 result_buffer[3] = 22;
12126 PUT_WORD (&result_buffer[4], GOOD);
12127 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12128 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12129 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12130 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12131 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12132 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12133 d |= LI2_PC_LOOPING_SUPPORTED;
12134 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12135 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12136 PUT_DWORD (&result_buffer[6], d);
12137 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12138 PUT_DWORD (&result_buffer[10], d / 2);
12139 PUT_DWORD (&result_buffer[14], d - 1);
12140 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12142 d = 0;
12143 for (i = 0; i < li_total_channels; i++)
12145 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12146 && (li_config_table[i].adapter->li_pri
12147 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12149 d++;
12153 PUT_DWORD (&result_buffer[18], d / 2);
12154 PUT_DWORD (&result_buffer[22], d - 1);
12156 break;
12158 case LI_REQ_CONNECT:
12159 if (li_parms[1].length == 8)
12161 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12162 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12164 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12165 UnMapId (Id), (char *)(FILE_), __LINE__));
12166 Info = _WRONG_MESSAGE_FORMAT;
12167 break;
12169 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12170 li_flags = GET_DWORD (li_req_parms[1].info);
12171 Info = li_check_main_plci (Id, plci);
12172 result_buffer[0] = 9;
12173 result_buffer[3] = 6;
12174 PUT_DWORD (&result_buffer[4], plci_b_id);
12175 PUT_WORD (&result_buffer[8], GOOD);
12176 if (Info != GOOD)
12177 break;
12178 result = plci->saved_msg.info;
12179 for (i = 0; i <= result_buffer[0]; i++)
12180 result[i] = result_buffer[i];
12181 plci_b_write_pos = plci->li_plci_b_write_pos;
12182 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12183 if (plci_b == NULL)
12184 break;
12185 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12186 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12187 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12188 plci->li_plci_b_write_pos = plci_b_write_pos;
12190 else
12192 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12193 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12195 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12196 UnMapId (Id), (char *)(FILE_), __LINE__));
12197 Info = _WRONG_MESSAGE_FORMAT;
12198 break;
12200 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12201 Info = li_check_main_plci (Id, plci);
12202 result_buffer[0] = 7;
12203 result_buffer[3] = 4;
12204 PUT_WORD (&result_buffer[4], Info);
12205 result_buffer[6] = 0;
12206 if (Info != GOOD)
12207 break;
12208 result = plci->saved_msg.info;
12209 for (i = 0; i <= result_buffer[0]; i++)
12210 result[i] = result_buffer[i];
12211 plci_b_write_pos = plci->li_plci_b_write_pos;
12212 participant_parms_pos = 0;
12213 result_pos = 7;
12214 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12215 while (participant_parms_pos < li_req_parms[1].length)
12217 result[result_pos] = 6;
12218 result_pos += 7;
12219 PUT_DWORD (&result[result_pos - 6], 0);
12220 PUT_WORD (&result[result_pos - 2], GOOD);
12221 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12222 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12224 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12225 UnMapId (Id), (char *)(FILE_), __LINE__));
12226 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12227 break;
12229 if (api_parse (&li_participant_struct[0].info[1],
12230 li_participant_struct[0].length, "dd", li_participant_parms))
12232 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12233 UnMapId (Id), (char *)(FILE_), __LINE__));
12234 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12235 break;
12237 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12238 li_flags = GET_DWORD (li_participant_parms[1].info);
12239 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12240 if (sizeof(result) - result_pos < 7)
12242 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12243 UnMapId (Id), (char *)(FILE_), __LINE__));
12244 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12245 break;
12247 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12248 if (plci_b != NULL)
12250 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12251 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12252 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12253 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12254 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12256 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12257 (&li_req_parms[1].info[1]));
12259 result[0] = (byte)(result_pos - 1);
12260 result[3] = (byte)(result_pos - 4);
12261 result[6] = (byte)(result_pos - 7);
12262 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12263 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12264 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12266 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12267 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12269 else
12270 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12271 plci->li_plci_b_write_pos = plci_b_write_pos;
12273 mixer_calculate_coefs (a);
12274 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12275 mixer_notify_update (plci, true);
12276 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12277 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12278 plci->command = 0;
12279 plci->li_cmd = GET_WORD (li_parms[0].info);
12280 start_internal_command (Id, plci, mixer_command);
12281 return (false);
12283 case LI_REQ_DISCONNECT:
12284 if (li_parms[1].length == 4)
12286 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12287 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12289 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12290 UnMapId (Id), (char *)(FILE_), __LINE__));
12291 Info = _WRONG_MESSAGE_FORMAT;
12292 break;
12294 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12295 Info = li_check_main_plci (Id, plci);
12296 result_buffer[0] = 9;
12297 result_buffer[3] = 6;
12298 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12299 PUT_WORD (&result_buffer[8], GOOD);
12300 if (Info != GOOD)
12301 break;
12302 result = plci->saved_msg.info;
12303 for (i = 0; i <= result_buffer[0]; i++)
12304 result[i] = result_buffer[i];
12305 plci_b_write_pos = plci->li_plci_b_write_pos;
12306 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12307 if (plci_b == NULL)
12308 break;
12309 li_update_connect (Id, a, plci, plci_b_id, false, 0);
12310 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12311 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12312 plci->li_plci_b_write_pos = plci_b_write_pos;
12314 else
12316 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12317 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12319 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12320 UnMapId (Id), (char *)(FILE_), __LINE__));
12321 Info = _WRONG_MESSAGE_FORMAT;
12322 break;
12324 Info = li_check_main_plci (Id, plci);
12325 result_buffer[0] = 7;
12326 result_buffer[3] = 4;
12327 PUT_WORD (&result_buffer[4], Info);
12328 result_buffer[6] = 0;
12329 if (Info != GOOD)
12330 break;
12331 result = plci->saved_msg.info;
12332 for (i = 0; i <= result_buffer[0]; i++)
12333 result[i] = result_buffer[i];
12334 plci_b_write_pos = plci->li_plci_b_write_pos;
12335 participant_parms_pos = 0;
12336 result_pos = 7;
12337 while (participant_parms_pos < li_req_parms[0].length)
12339 result[result_pos] = 6;
12340 result_pos += 7;
12341 PUT_DWORD (&result[result_pos - 6], 0);
12342 PUT_WORD (&result[result_pos - 2], GOOD);
12343 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12344 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12346 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12347 UnMapId (Id), (char *)(FILE_), __LINE__));
12348 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12349 break;
12351 if (api_parse (&li_participant_struct[0].info[1],
12352 li_participant_struct[0].length, "d", li_participant_parms))
12354 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12355 UnMapId (Id), (char *)(FILE_), __LINE__));
12356 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12357 break;
12359 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12360 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12361 if (sizeof(result) - result_pos < 7)
12363 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12364 UnMapId (Id), (char *)(FILE_), __LINE__));
12365 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12366 break;
12368 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12369 if (plci_b != NULL)
12371 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12372 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12373 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12375 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12376 (&li_req_parms[0].info[1]));
12378 result[0] = (byte)(result_pos - 1);
12379 result[3] = (byte)(result_pos - 4);
12380 result[6] = (byte)(result_pos - 7);
12381 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12382 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12383 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12385 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12386 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12388 else
12389 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12390 plci->li_plci_b_write_pos = plci_b_write_pos;
12392 mixer_calculate_coefs (a);
12393 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12394 mixer_notify_update (plci, true);
12395 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12396 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12397 plci->command = 0;
12398 plci->li_cmd = GET_WORD (li_parms[0].info);
12399 start_internal_command (Id, plci, mixer_command);
12400 return (false);
12402 case LI_REQ_SILENT_UPDATE:
12403 if (!plci || !plci->State
12404 || !plci->NL.Id || plci->nl_remove_id
12405 || (plci->li_bchannel_id == 0)
12406 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12408 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12409 UnMapId (Id), (char *)(FILE_), __LINE__));
12410 return (false);
12412 plci_b_write_pos = plci->li_plci_b_write_pos;
12413 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12414 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12416 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12417 UnMapId (Id), (char *)(FILE_), __LINE__));
12418 return (false);
12420 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12421 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12422 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12424 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12425 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12427 else
12428 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12429 plci->li_plci_b_write_pos = plci_b_write_pos;
12430 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12431 plci->command = 0;
12432 plci->li_cmd = GET_WORD (li_parms[0].info);
12433 start_internal_command (Id, plci, mixer_command);
12434 return (false);
12436 default:
12437 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12438 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12439 Info = _FACILITY_NOT_SUPPORTED;
12442 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12443 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12444 return (false);
12448 static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12450 dword d;
12451 DIVA_CAPI_ADAPTER *a;
12452 byte result[12];
12454 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12455 UnMapId (Id), (char *)(FILE_), __LINE__));
12457 a = plci->adapter;
12458 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12462 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12463 if (!(d & LI_PLCI_B_SKIP_FLAG))
12465 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12467 if (d & LI_PLCI_B_DISC_FLAG)
12469 result[0] = 5;
12470 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12471 result[3] = 2;
12472 PUT_WORD (&result[4], _LI_USER_INITIATED);
12474 else
12476 result[0] = 7;
12477 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12478 result[3] = 4;
12479 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12482 else
12484 if (d & LI_PLCI_B_DISC_FLAG)
12486 result[0] = 9;
12487 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12488 result[3] = 6;
12489 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12490 PUT_WORD (&result[8], _LI_USER_INITIATED);
12492 else
12494 result[0] = 7;
12495 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12496 result[3] = 4;
12497 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12500 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12501 "ws", SELECTOR_LINE_INTERCONNECT, result);
12503 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12504 0 : plci->li_plci_b_read_pos + 1;
12505 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12510 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12512 word i, j, ch;
12513 struct xconnect_transfer_address_s s, *p;
12514 DIVA_CAPI_ADAPTER *a;
12516 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12517 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12519 a = plci->adapter;
12520 i = 1;
12521 for (i = 1; i < length; i += 16)
12523 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12524 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12525 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12526 ch = msg[i+12] | (msg[i+13] << 8);
12527 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12528 if (!a->li_pri && (plci->li_bchannel_id == 2))
12529 j = 1 - j;
12530 j += a->li_base;
12531 if (ch & XCONNECT_CHANNEL_PORT_PC)
12532 p = &(li_config_table[j].send_pc);
12533 else
12534 p = &(li_config_table[j].send_b);
12535 p->card_address.low = s.card_address.low;
12536 p->card_address.high = s.card_address.high;
12537 p->offset = s.offset;
12538 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12540 if (plci->internal_command_queue[0]
12541 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12542 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12543 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12545 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12546 if (!plci->internal_command)
12547 next_internal_command (Id, plci);
12549 mixer_notify_update (plci, true);
12553 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12556 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12557 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12562 static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12564 word plci_b_write_pos;
12566 plci_b_write_pos = plci->li_plci_b_write_pos;
12567 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12568 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12570 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12571 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12572 (char *)(FILE_), __LINE__));
12573 return (false);
12575 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12576 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12577 plci->li_plci_b_write_pos = plci_b_write_pos;
12578 return (true);
12582 static void mixer_remove (PLCI *plci)
12584 DIVA_CAPI_ADAPTER *a;
12585 PLCI *notify_plci;
12586 dword plci_b_id;
12587 word i, j;
12589 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12590 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12591 (char *)(FILE_), __LINE__));
12593 a = plci->adapter;
12594 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12595 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12597 if ((plci->li_bchannel_id != 0)
12598 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12600 i = a->li_base + (plci->li_bchannel_id - 1);
12601 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12603 for (j = 0; j < li_total_channels; j++)
12605 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12606 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12608 notify_plci = li_config_table[j].plci;
12609 if ((notify_plci != NULL)
12610 && (notify_plci != plci)
12611 && (notify_plci->appl != NULL)
12612 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12613 && (notify_plci->State)
12614 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12616 mixer_notify_source_removed (notify_plci, plci_b_id);
12620 mixer_clear_config (plci);
12621 mixer_calculate_coefs (a);
12622 mixer_notify_update (plci, true);
12624 li_config_table[i].plci = NULL;
12625 plci->li_bchannel_id = 0;
12631 /*------------------------------------------------------------------*/
12632 /* Echo canceller facilities */
12633 /*------------------------------------------------------------------*/
12636 static void ec_write_parameters (PLCI *plci)
12638 word w;
12639 byte parameter_buffer[6];
12641 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12642 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12643 (char *)(FILE_), __LINE__));
12645 parameter_buffer[0] = 5;
12646 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12647 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12648 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12649 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12650 PUT_WORD (&parameter_buffer[4], w);
12651 add_p (plci, FTY, parameter_buffer);
12652 sig_req (plci, TEL_CTRL, 0);
12653 send_req (plci);
12657 static void ec_clear_config (PLCI *plci)
12660 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12661 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12662 (char *)(FILE_), __LINE__));
12664 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12665 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12666 plci->ec_tail_length = 0;
12670 static void ec_prepare_switch (dword Id, PLCI *plci)
12673 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12674 UnMapId (Id), (char *)(FILE_), __LINE__));
12679 static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12682 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12683 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12685 return (GOOD);
12689 static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12691 word Info;
12693 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12694 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12696 Info = GOOD;
12697 if (plci->B1_facilities & B1_FACILITY_EC)
12699 switch (plci->adjust_b_state)
12701 case ADJUST_B_RESTORE_EC_1:
12702 plci->internal_command = plci->adjust_b_command;
12703 if (plci->sig_req)
12705 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12706 break;
12708 ec_write_parameters (plci);
12709 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12710 break;
12711 case ADJUST_B_RESTORE_EC_2:
12712 if ((Rc != OK) && (Rc != OK_FC))
12714 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12715 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12716 Info = _WRONG_STATE;
12717 break;
12719 break;
12722 return (Info);
12726 static void ec_command (dword Id, PLCI *plci, byte Rc)
12728 word internal_command, Info;
12729 byte result[8];
12731 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12732 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12733 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12735 Info = GOOD;
12736 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12738 result[0] = 2;
12739 PUT_WORD (&result[1], EC_SUCCESS);
12741 else
12743 result[0] = 5;
12744 PUT_WORD (&result[1], plci->ec_cmd);
12745 result[3] = 2;
12746 PUT_WORD (&result[4], GOOD);
12748 internal_command = plci->internal_command;
12749 plci->internal_command = 0;
12750 switch (plci->ec_cmd)
12752 case EC_ENABLE_OPERATION:
12753 case EC_FREEZE_COEFFICIENTS:
12754 case EC_RESUME_COEFFICIENT_UPDATE:
12755 case EC_RESET_COEFFICIENTS:
12756 switch (internal_command)
12758 default:
12759 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12760 B1_FACILITY_EC), EC_COMMAND_1);
12761 case EC_COMMAND_1:
12762 if (adjust_b_process (Id, plci, Rc) != GOOD)
12764 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12765 UnMapId (Id), (char *)(FILE_), __LINE__));
12766 Info = _FACILITY_NOT_SUPPORTED;
12767 break;
12769 if (plci->internal_command)
12770 return;
12771 case EC_COMMAND_2:
12772 if (plci->sig_req)
12774 plci->internal_command = EC_COMMAND_2;
12775 return;
12777 plci->internal_command = EC_COMMAND_3;
12778 ec_write_parameters (plci);
12779 return;
12780 case EC_COMMAND_3:
12781 if ((Rc != OK) && (Rc != OK_FC))
12783 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12784 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12785 Info = _FACILITY_NOT_SUPPORTED;
12786 break;
12788 break;
12790 break;
12792 case EC_DISABLE_OPERATION:
12793 switch (internal_command)
12795 default:
12796 case EC_COMMAND_1:
12797 if (plci->B1_facilities & B1_FACILITY_EC)
12799 if (plci->sig_req)
12801 plci->internal_command = EC_COMMAND_1;
12802 return;
12804 plci->internal_command = EC_COMMAND_2;
12805 ec_write_parameters (plci);
12806 return;
12808 Rc = OK;
12809 case EC_COMMAND_2:
12810 if ((Rc != OK) && (Rc != OK_FC))
12812 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12813 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12814 Info = _FACILITY_NOT_SUPPORTED;
12815 break;
12817 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12818 ~B1_FACILITY_EC), EC_COMMAND_3);
12819 case EC_COMMAND_3:
12820 if (adjust_b_process (Id, plci, Rc) != GOOD)
12822 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12823 UnMapId (Id), (char *)(FILE_), __LINE__));
12824 Info = _FACILITY_NOT_SUPPORTED;
12825 break;
12827 if (plci->internal_command)
12828 return;
12829 break;
12831 break;
12833 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12834 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12835 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12839 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12841 word Info;
12842 word opt;
12843 API_PARSE ec_parms[3];
12844 byte result[16];
12846 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12847 UnMapId (Id), (char *)(FILE_), __LINE__));
12849 Info = GOOD;
12850 result[0] = 0;
12851 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12853 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12854 UnMapId (Id), (char *)(FILE_), __LINE__));
12855 Info = _FACILITY_NOT_SUPPORTED;
12857 else
12859 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12861 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12863 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12864 UnMapId (Id), (char *)(FILE_), __LINE__));
12865 Info = _WRONG_MESSAGE_FORMAT;
12867 else
12869 if (plci == NULL)
12871 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12872 UnMapId (Id), (char *)(FILE_), __LINE__));
12873 Info = _WRONG_IDENTIFIER;
12875 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12877 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12878 UnMapId (Id), (char *)(FILE_), __LINE__));
12879 Info = _WRONG_STATE;
12881 else
12883 plci->command = 0;
12884 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12885 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12886 result[0] = 2;
12887 PUT_WORD (&result[1], EC_SUCCESS);
12888 if (msg[1].length >= 4)
12890 opt = GET_WORD (&ec_parms[0].info[2]);
12891 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12892 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12893 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12894 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12895 if (opt & EC_DETECT_DISABLE_TONE)
12896 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12897 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12898 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12899 if (msg[1].length >= 6)
12901 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12904 switch (plci->ec_cmd)
12906 case EC_ENABLE_OPERATION:
12907 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12908 start_internal_command (Id, plci, ec_command);
12909 return (false);
12911 case EC_DISABLE_OPERATION:
12912 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12913 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12914 LEC_RESET_COEFFICIENTS;
12915 start_internal_command (Id, plci, ec_command);
12916 return (false);
12918 case EC_FREEZE_COEFFICIENTS:
12919 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12920 start_internal_command (Id, plci, ec_command);
12921 return (false);
12923 case EC_RESUME_COEFFICIENT_UPDATE:
12924 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12925 start_internal_command (Id, plci, ec_command);
12926 return (false);
12928 case EC_RESET_COEFFICIENTS:
12929 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12930 start_internal_command (Id, plci, ec_command);
12931 return (false);
12933 default:
12934 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12935 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12936 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12941 else
12943 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12945 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12946 UnMapId (Id), (char *)(FILE_), __LINE__));
12947 Info = _WRONG_MESSAGE_FORMAT;
12949 else
12951 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12953 result[0] = 11;
12954 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12955 result[3] = 8;
12956 PUT_WORD (&result[4], GOOD);
12957 PUT_WORD (&result[6], 0x0007);
12958 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12959 PUT_WORD (&result[10], 0);
12961 else if (plci == NULL)
12963 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12964 UnMapId (Id), (char *)(FILE_), __LINE__));
12965 Info = _WRONG_IDENTIFIER;
12967 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12969 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12970 UnMapId (Id), (char *)(FILE_), __LINE__));
12971 Info = _WRONG_STATE;
12973 else
12975 plci->command = 0;
12976 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12977 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12978 result[0] = 5;
12979 PUT_WORD (&result[1], plci->ec_cmd);
12980 result[3] = 2;
12981 PUT_WORD (&result[4], GOOD);
12982 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12983 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12984 plci->ec_tail_length = 0;
12985 if (ec_parms[1].length >= 2)
12987 opt = GET_WORD (&ec_parms[1].info[1]);
12988 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12989 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12990 if (opt & EC_DETECT_DISABLE_TONE)
12991 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12992 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12993 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12994 if (ec_parms[1].length >= 4)
12996 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12999 switch (plci->ec_cmd)
13001 case EC_ENABLE_OPERATION:
13002 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
13003 start_internal_command (Id, plci, ec_command);
13004 return (false);
13006 case EC_DISABLE_OPERATION:
13007 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
13008 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
13009 LEC_RESET_COEFFICIENTS;
13010 start_internal_command (Id, plci, ec_command);
13011 return (false);
13013 default:
13014 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
13015 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13016 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13022 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13023 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13024 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13025 return (false);
13029 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13031 byte result[8];
13033 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13034 UnMapId (Id), (char *)(FILE_), __LINE__));
13036 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13038 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13040 result[0] = 2;
13041 PUT_WORD (&result[1], 0);
13042 switch (msg[1])
13044 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13046 break;
13047 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13049 break;
13050 case LEC_DISABLE_RELEASED:
13051 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13052 break;
13055 else
13057 result[0] = 5;
13058 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13059 result[3] = 2;
13060 PUT_WORD (&result[4], 0);
13061 switch (msg[1])
13063 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13064 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13065 break;
13066 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13067 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13068 break;
13069 case LEC_DISABLE_RELEASED:
13070 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13071 break;
13074 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13075 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13081 /*------------------------------------------------------------------*/
13082 /* Advanced voice */
13083 /*------------------------------------------------------------------*/
13085 static void adv_voice_write_coefs (PLCI *plci, word write_command)
13087 DIVA_CAPI_ADAPTER *a;
13088 word i;
13089 byte *p;
13091 word w, n, j, k;
13092 byte ch_map[MIXER_CHANNELS_BRI];
13094 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13096 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13097 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13098 (char *)(FILE_), __LINE__, write_command));
13100 a = plci->adapter;
13101 p = coef_buffer + 1;
13102 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13103 i = 0;
13104 while (i + sizeof(word) <= a->adv_voice_coef_length)
13106 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13107 p += 2;
13108 i += 2;
13110 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13112 PUT_WORD (p, 0x8000);
13113 p += 2;
13114 i += 2;
13117 if (!a->li_pri && (plci->li_bchannel_id == 0))
13119 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13121 plci->li_bchannel_id = 1;
13122 li_config_table[a->li_base].plci = plci;
13123 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13124 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13125 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13127 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13129 plci->li_bchannel_id = 2;
13130 li_config_table[a->li_base + 1].plci = plci;
13131 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13132 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13133 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13136 if (!a->li_pri && (plci->li_bchannel_id != 0)
13137 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13139 i = a->li_base + (plci->li_bchannel_id - 1);
13140 switch (write_command)
13142 case ADV_VOICE_WRITE_ACTIVATION:
13143 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13144 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13145 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13147 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13148 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13150 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13152 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13153 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13154 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13155 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13157 mixer_calculate_coefs (a);
13158 li_config_table[i].curchnl = li_config_table[i].channel;
13159 li_config_table[j].curchnl = li_config_table[j].channel;
13160 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13161 li_config_table[k].curchnl = li_config_table[k].channel;
13162 break;
13164 case ADV_VOICE_WRITE_DEACTIVATION:
13165 for (j = 0; j < li_total_channels; j++)
13167 li_config_table[i].flag_table[j] = 0;
13168 li_config_table[j].flag_table[i] = 0;
13170 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13171 for (j = 0; j < li_total_channels; j++)
13173 li_config_table[k].flag_table[j] = 0;
13174 li_config_table[j].flag_table[k] = 0;
13176 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13178 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13179 for (j = 0; j < li_total_channels; j++)
13181 li_config_table[k].flag_table[j] = 0;
13182 li_config_table[j].flag_table[k] = 0;
13185 mixer_calculate_coefs (a);
13186 break;
13188 if (plci->B1_facilities & B1_FACILITY_MIXER)
13190 w = 0;
13191 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13192 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13193 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13194 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13195 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13196 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13197 *(p++) = (byte) w;
13198 *(p++) = (byte)(w >> 8);
13199 for (j = 0; j < sizeof(ch_map); j += 2)
13201 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13202 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13204 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13206 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13207 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13208 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13210 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13211 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13212 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13214 else
13216 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13217 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13221 else
13223 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13224 *(p++) = a->adv_voice_coef_buffer[i];
13227 else
13230 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13231 *(p++) = a->adv_voice_coef_buffer[i];
13233 coef_buffer[0] = (p - coef_buffer) - 1;
13234 add_p (plci, FTY, coef_buffer);
13235 sig_req (plci, TEL_CTRL, 0);
13236 send_req (plci);
13240 static void adv_voice_clear_config (PLCI *plci)
13242 DIVA_CAPI_ADAPTER *a;
13244 word i, j;
13247 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13248 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13249 (char *)(FILE_), __LINE__));
13251 a = plci->adapter;
13252 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13254 a->adv_voice_coef_length = 0;
13256 if (!a->li_pri && (plci->li_bchannel_id != 0)
13257 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13259 i = a->li_base + (plci->li_bchannel_id - 1);
13260 li_config_table[i].curchnl = 0;
13261 li_config_table[i].channel = 0;
13262 li_config_table[i].chflags = 0;
13263 for (j = 0; j < li_total_channels; j++)
13265 li_config_table[i].flag_table[j] = 0;
13266 li_config_table[j].flag_table[i] = 0;
13267 li_config_table[i].coef_table[j] = 0;
13268 li_config_table[j].coef_table[i] = 0;
13270 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13271 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13272 li_config_table[i].curchnl = 0;
13273 li_config_table[i].channel = 0;
13274 li_config_table[i].chflags = 0;
13275 for (j = 0; j < li_total_channels; j++)
13277 li_config_table[i].flag_table[j] = 0;
13278 li_config_table[j].flag_table[i] = 0;
13279 li_config_table[i].coef_table[j] = 0;
13280 li_config_table[j].coef_table[i] = 0;
13282 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13284 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13285 li_config_table[i].curchnl = 0;
13286 li_config_table[i].channel = 0;
13287 li_config_table[i].chflags = 0;
13288 for (j = 0; j < li_total_channels; j++)
13290 li_config_table[i].flag_table[j] = 0;
13291 li_config_table[j].flag_table[i] = 0;
13292 li_config_table[i].coef_table[j] = 0;
13293 li_config_table[j].coef_table[i] = 0;
13302 static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13305 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13306 UnMapId (Id), (char *)(FILE_), __LINE__));
13311 static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13314 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13315 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13317 return (GOOD);
13321 static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13323 DIVA_CAPI_ADAPTER *a;
13324 word Info;
13326 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13327 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13329 Info = GOOD;
13330 a = plci->adapter;
13331 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13332 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13334 switch (plci->adjust_b_state)
13336 case ADJUST_B_RESTORE_VOICE_1:
13337 plci->internal_command = plci->adjust_b_command;
13338 if (plci->sig_req)
13340 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13341 break;
13343 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13344 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13345 break;
13346 case ADJUST_B_RESTORE_VOICE_2:
13347 if ((Rc != OK) && (Rc != OK_FC))
13349 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13350 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13351 Info = _WRONG_STATE;
13352 break;
13354 break;
13357 return (Info);
13363 /*------------------------------------------------------------------*/
13364 /* B1 resource switching */
13365 /*------------------------------------------------------------------*/
13367 static byte b1_facilities_table[] =
13369 0x00, /* 0 No bchannel resources */
13370 0x00, /* 1 Codec (automatic law) */
13371 0x00, /* 2 Codec (A-law) */
13372 0x00, /* 3 Codec (y-law) */
13373 0x00, /* 4 HDLC for X.21 */
13374 0x00, /* 5 HDLC */
13375 0x00, /* 6 External Device 0 */
13376 0x00, /* 7 External Device 1 */
13377 0x00, /* 8 HDLC 56k */
13378 0x00, /* 9 Transparent */
13379 0x00, /* 10 Loopback to network */
13380 0x00, /* 11 Test pattern to net */
13381 0x00, /* 12 Rate adaptation sync */
13382 0x00, /* 13 Rate adaptation async */
13383 0x00, /* 14 R-Interface */
13384 0x00, /* 15 HDLC 128k leased line */
13385 0x00, /* 16 FAX */
13386 0x00, /* 17 Modem async */
13387 0x00, /* 18 Modem sync HDLC */
13388 0x00, /* 19 V.110 async HDLC */
13389 0x12, /* 20 Adv voice (Trans,mixer) */
13390 0x00, /* 21 Codec connected to IC */
13391 0x0c, /* 22 Trans,DTMF */
13392 0x1e, /* 23 Trans,DTMF+mixer */
13393 0x1f, /* 24 Trans,DTMF+mixer+local */
13394 0x13, /* 25 Trans,mixer+local */
13395 0x12, /* 26 HDLC,mixer */
13396 0x12, /* 27 HDLC 56k,mixer */
13397 0x2c, /* 28 Trans,LEC+DTMF */
13398 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13399 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13400 0x2c, /* 31 RTP,LEC+DTMF */
13401 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13402 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13403 0x00, /* 34 Signaling task */
13404 0x00, /* 35 PIAFS */
13405 0x0c, /* 36 Trans,DTMF+TONE */
13406 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13407 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13411 static word get_b1_facilities (PLCI * plci, byte b1_resource)
13413 word b1_facilities;
13415 b1_facilities = b1_facilities_table[b1_resource];
13416 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13419 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13420 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13423 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13424 b1_facilities |= B1_FACILITY_DTMFX;
13425 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13426 b1_facilities |= B1_FACILITY_DTMFR;
13429 if ((b1_resource == 17) || (b1_resource == 18))
13431 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13432 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13435 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13436 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13437 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13439 return (b1_facilities);
13443 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13445 byte b;
13447 switch (b1_resource)
13449 case 5:
13450 case 26:
13451 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13452 b = 26;
13453 else
13454 b = 5;
13455 break;
13457 case 8:
13458 case 27:
13459 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13460 b = 27;
13461 else
13462 b = 8;
13463 break;
13465 case 9:
13466 case 20:
13467 case 22:
13468 case 23:
13469 case 24:
13470 case 25:
13471 case 28:
13472 case 29:
13473 case 30:
13474 case 36:
13475 case 37:
13476 case 38:
13477 if (b1_facilities & B1_FACILITY_EC)
13479 if (b1_facilities & B1_FACILITY_LOCAL)
13480 b = 30;
13481 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482 b = 29;
13483 else
13484 b = 28;
13487 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13488 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13489 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13491 if (b1_facilities & B1_FACILITY_LOCAL)
13492 b = 38;
13493 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13494 b = 37;
13495 else
13496 b = 36;
13499 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13500 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13501 || ((b1_facilities & B1_FACILITY_DTMFR)
13502 && ((b1_facilities & B1_FACILITY_MIXER)
13503 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13504 || ((b1_facilities & B1_FACILITY_DTMFX)
13505 && ((b1_facilities & B1_FACILITY_MIXER)
13506 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13508 if (b1_facilities & B1_FACILITY_LOCAL)
13509 b = 24;
13510 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13511 b = 23;
13512 else
13513 b = 22;
13515 else
13517 if (b1_facilities & B1_FACILITY_LOCAL)
13518 b = 25;
13519 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520 b = 20;
13521 else
13522 b = 9;
13524 break;
13526 case 31:
13527 case 32:
13528 case 33:
13529 if (b1_facilities & B1_FACILITY_LOCAL)
13530 b = 33;
13531 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13532 b = 32;
13533 else
13534 b = 31;
13535 break;
13537 default:
13538 b = b1_resource;
13540 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13541 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13542 (char *)(FILE_), __LINE__,
13543 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13544 return (b);
13548 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13550 word removed_facilities;
13552 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13553 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13554 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13555 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13557 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13558 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13560 if (removed_facilities & B1_FACILITY_EC)
13561 ec_clear_config (plci);
13564 if (removed_facilities & B1_FACILITY_DTMFR)
13566 dtmf_rec_clear_config (plci);
13567 dtmf_parameter_clear_config (plci);
13569 if (removed_facilities & B1_FACILITY_DTMFX)
13570 dtmf_send_clear_config (plci);
13573 if (removed_facilities & B1_FACILITY_MIXER)
13574 mixer_clear_config (plci);
13576 if (removed_facilities & B1_FACILITY_VOICE)
13577 adv_voice_clear_config (plci);
13578 plci->B1_facilities = new_b1_facilities;
13582 static void adjust_b_clear (PLCI *plci)
13585 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13586 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13587 (char *)(FILE_), __LINE__));
13589 plci->adjust_b_restore = false;
13593 static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13595 word Info;
13596 byte b1_resource;
13597 NCCI * ncci_ptr;
13598 API_PARSE bp[2];
13600 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13601 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13603 Info = GOOD;
13604 switch (plci->adjust_b_state)
13606 case ADJUST_B_START:
13607 if ((plci->adjust_b_parms_msg == NULL)
13608 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13609 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13610 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13612 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13613 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13614 if (b1_resource == plci->B1_resource)
13616 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13617 break;
13619 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13621 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13622 UnMapId (Id), (char *)(FILE_), __LINE__,
13623 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13624 Info = _WRONG_STATE;
13625 break;
13628 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13631 mixer_prepare_switch (Id, plci);
13634 dtmf_prepare_switch (Id, plci);
13635 dtmf_parameter_prepare_switch (Id, plci);
13638 ec_prepare_switch (Id, plci);
13640 adv_voice_prepare_switch (Id, plci);
13642 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13643 Rc = OK;
13644 case ADJUST_B_SAVE_MIXER_1:
13645 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13648 Info = mixer_save_config (Id, plci, Rc);
13649 if ((Info != GOOD) || plci->internal_command)
13650 break;
13653 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13654 Rc = OK;
13655 case ADJUST_B_SAVE_DTMF_1:
13656 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13659 Info = dtmf_save_config (Id, plci, Rc);
13660 if ((Info != GOOD) || plci->internal_command)
13661 break;
13664 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13665 case ADJUST_B_REMOVE_L23_1:
13666 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13667 && plci->NL.Id && !plci->nl_remove_id)
13669 plci->internal_command = plci->adjust_b_command;
13670 if (plci->adjust_b_ncci != 0)
13672 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13673 while (ncci_ptr->data_pending)
13675 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13676 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13678 while (ncci_ptr->data_ack_pending)
13679 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13681 nl_req_ncci (plci, REMOVE,
13682 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13683 send_req (plci);
13684 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13685 break;
13687 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13688 Rc = OK;
13689 case ADJUST_B_REMOVE_L23_2:
13690 if ((Rc != OK) && (Rc != OK_FC))
13692 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13693 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13694 Info = _WRONG_STATE;
13695 break;
13697 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13699 if (plci_nl_busy (plci))
13701 plci->internal_command = plci->adjust_b_command;
13702 break;
13705 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13706 Rc = OK;
13707 case ADJUST_B_SAVE_EC_1:
13708 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13711 Info = ec_save_config (Id, plci, Rc);
13712 if ((Info != GOOD) || plci->internal_command)
13713 break;
13716 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13717 Rc = OK;
13718 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13719 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13722 Info = dtmf_parameter_save_config (Id, plci, Rc);
13723 if ((Info != GOOD) || plci->internal_command)
13724 break;
13727 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13728 Rc = OK;
13729 case ADJUST_B_SAVE_VOICE_1:
13730 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13732 Info = adv_voice_save_config (Id, plci, Rc);
13733 if ((Info != GOOD) || plci->internal_command)
13734 break;
13736 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13737 case ADJUST_B_SWITCH_L1_1:
13738 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13740 if (plci->sig_req)
13742 plci->internal_command = plci->adjust_b_command;
13743 break;
13745 if (plci->adjust_b_parms_msg != NULL)
13746 api_load_msg (plci->adjust_b_parms_msg, bp);
13747 else
13748 api_load_msg (&plci->B_protocol, bp);
13749 Info = add_b1 (plci, bp,
13750 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13751 plci->adjust_b_facilities);
13752 if (Info != GOOD)
13754 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13755 UnMapId (Id), (char *)(FILE_), __LINE__,
13756 plci->B1_resource, plci->adjust_b_facilities));
13757 break;
13759 plci->internal_command = plci->adjust_b_command;
13760 sig_req (plci, RESOURCES, 0);
13761 send_req (plci);
13762 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13763 break;
13765 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13766 Rc = OK;
13767 case ADJUST_B_SWITCH_L1_2:
13768 if ((Rc != OK) && (Rc != OK_FC))
13770 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13771 UnMapId (Id), (char *)(FILE_), __LINE__,
13772 Rc, plci->B1_resource, plci->adjust_b_facilities));
13773 Info = _WRONG_STATE;
13774 break;
13776 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13777 Rc = OK;
13778 case ADJUST_B_RESTORE_VOICE_1:
13779 case ADJUST_B_RESTORE_VOICE_2:
13780 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13782 Info = adv_voice_restore_config (Id, plci, Rc);
13783 if ((Info != GOOD) || plci->internal_command)
13784 break;
13786 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13787 Rc = OK;
13788 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13789 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13790 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13793 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13794 if ((Info != GOOD) || plci->internal_command)
13795 break;
13798 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13799 Rc = OK;
13800 case ADJUST_B_RESTORE_EC_1:
13801 case ADJUST_B_RESTORE_EC_2:
13802 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13805 Info = ec_restore_config (Id, plci, Rc);
13806 if ((Info != GOOD) || plci->internal_command)
13807 break;
13810 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13811 case ADJUST_B_ASSIGN_L23_1:
13812 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13814 if (plci_nl_busy (plci))
13816 plci->internal_command = plci->adjust_b_command;
13817 break;
13819 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13820 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13821 if (plci->adjust_b_parms_msg != NULL)
13822 api_load_msg (plci->adjust_b_parms_msg, bp);
13823 else
13824 api_load_msg (&plci->B_protocol, bp);
13825 Info = add_b23 (plci, bp);
13826 if (Info != GOOD)
13828 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13829 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13830 break;
13832 plci->internal_command = plci->adjust_b_command;
13833 nl_req_ncci (plci, ASSIGN, 0);
13834 send_req (plci);
13835 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13836 break;
13838 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13839 Rc = ASSIGN_OK;
13840 case ADJUST_B_ASSIGN_L23_2:
13841 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13843 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13844 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13845 Info = _WRONG_STATE;
13846 break;
13848 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13850 if (Rc != ASSIGN_OK)
13852 plci->internal_command = plci->adjust_b_command;
13853 break;
13856 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13858 plci->adjust_b_restore = true;
13859 break;
13861 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13862 case ADJUST_B_CONNECT_1:
13863 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13865 plci->internal_command = plci->adjust_b_command;
13866 if (plci_nl_busy (plci))
13867 break;
13868 nl_req_ncci (plci, N_CONNECT, 0);
13869 send_req (plci);
13870 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13871 break;
13873 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13874 Rc = OK;
13875 case ADJUST_B_CONNECT_2:
13876 case ADJUST_B_CONNECT_3:
13877 case ADJUST_B_CONNECT_4:
13878 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13880 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13881 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13882 Info = _WRONG_STATE;
13883 break;
13885 if (Rc == OK)
13887 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13889 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13890 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13892 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13893 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13894 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13895 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13897 else if (Rc == 0)
13899 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13900 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13901 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13902 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13904 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13906 plci->internal_command = plci->adjust_b_command;
13907 break;
13909 Rc = OK;
13910 case ADJUST_B_RESTORE_DTMF_1:
13911 case ADJUST_B_RESTORE_DTMF_2:
13912 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13915 Info = dtmf_restore_config (Id, plci, Rc);
13916 if ((Info != GOOD) || plci->internal_command)
13917 break;
13920 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13921 Rc = OK;
13922 case ADJUST_B_RESTORE_MIXER_1:
13923 case ADJUST_B_RESTORE_MIXER_2:
13924 case ADJUST_B_RESTORE_MIXER_3:
13925 case ADJUST_B_RESTORE_MIXER_4:
13926 case ADJUST_B_RESTORE_MIXER_5:
13927 case ADJUST_B_RESTORE_MIXER_6:
13928 case ADJUST_B_RESTORE_MIXER_7:
13929 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13932 Info = mixer_restore_config (Id, plci, Rc);
13933 if ((Info != GOOD) || plci->internal_command)
13934 break;
13937 plci->adjust_b_state = ADJUST_B_END;
13938 case ADJUST_B_END:
13939 break;
13941 return (Info);
13945 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13948 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13949 UnMapId (Id), (char *)(FILE_), __LINE__,
13950 plci->B1_resource, b1_facilities));
13952 plci->adjust_b_parms_msg = bp_msg;
13953 plci->adjust_b_facilities = b1_facilities;
13954 plci->adjust_b_command = internal_command;
13955 plci->adjust_b_ncci = (word)(Id >> 16);
13956 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13957 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13958 else
13959 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13960 plci->adjust_b_state = ADJUST_B_START;
13961 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13962 UnMapId (Id), (char *)(FILE_), __LINE__,
13963 plci->B1_resource, b1_facilities));
13967 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13969 word internal_command;
13971 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13972 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13974 internal_command = plci->internal_command;
13975 plci->internal_command = 0;
13976 switch (internal_command)
13978 default:
13979 plci->command = 0;
13980 if (plci->req_in != 0)
13982 plci->internal_command = ADJUST_B_RESTORE_1;
13983 break;
13985 Rc = OK;
13986 case ADJUST_B_RESTORE_1:
13987 if ((Rc != OK) && (Rc != OK_FC))
13989 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13990 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13992 plci->adjust_b_parms_msg = NULL;
13993 plci->adjust_b_facilities = plci->B1_facilities;
13994 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13995 plci->adjust_b_ncci = (word)(Id >> 16);
13996 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13997 plci->adjust_b_state = ADJUST_B_START;
13998 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13999 UnMapId (Id), (char *)(FILE_), __LINE__));
14000 case ADJUST_B_RESTORE_2:
14001 if (adjust_b_process (Id, plci, Rc) != GOOD)
14003 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
14004 UnMapId (Id), (char *)(FILE_), __LINE__));
14006 if (plci->internal_command)
14007 break;
14008 break;
14013 static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
14015 word Info;
14016 word internal_command;
14018 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14019 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14021 Info = GOOD;
14022 internal_command = plci->internal_command;
14023 plci->internal_command = 0;
14024 switch (internal_command)
14026 default:
14027 plci->command = 0;
14028 plci->adjust_b_parms_msg = NULL;
14029 plci->adjust_b_facilities = plci->B1_facilities;
14030 plci->adjust_b_command = RESET_B3_COMMAND_1;
14031 plci->adjust_b_ncci = (word)(Id >> 16);
14032 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14033 plci->adjust_b_state = ADJUST_B_START;
14034 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14035 UnMapId (Id), (char *)(FILE_), __LINE__));
14036 case RESET_B3_COMMAND_1:
14037 Info = adjust_b_process (Id, plci, Rc);
14038 if (Info != GOOD)
14040 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14041 UnMapId (Id), (char *)(FILE_), __LINE__));
14042 break;
14044 if (plci->internal_command)
14045 return;
14046 break;
14048 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14049 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14053 static void select_b_command (dword Id, PLCI *plci, byte Rc)
14055 word Info;
14056 word internal_command;
14057 byte esc_chi[3];
14059 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14060 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14062 Info = GOOD;
14063 internal_command = plci->internal_command;
14064 plci->internal_command = 0;
14065 switch (internal_command)
14067 default:
14068 plci->command = 0;
14069 plci->adjust_b_parms_msg = &plci->saved_msg;
14070 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14071 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14072 else
14073 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14074 plci->adjust_b_command = SELECT_B_COMMAND_1;
14075 plci->adjust_b_ncci = (word)(Id >> 16);
14076 if (plci->saved_msg.parms[0].length == 0)
14078 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14079 ADJUST_B_MODE_NO_RESOURCE;
14081 else
14083 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14084 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14086 plci->adjust_b_state = ADJUST_B_START;
14087 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14088 UnMapId (Id), (char *)(FILE_), __LINE__));
14089 case SELECT_B_COMMAND_1:
14090 Info = adjust_b_process (Id, plci, Rc);
14091 if (Info != GOOD)
14093 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14094 UnMapId (Id), (char *)(FILE_), __LINE__));
14095 break;
14097 if (plci->internal_command)
14098 return;
14099 if (plci->tel == ADV_VOICE)
14101 esc_chi[0] = 0x02;
14102 esc_chi[1] = 0x18;
14103 esc_chi[2] = plci->b_channel;
14104 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14106 break;
14108 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14112 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14114 word Info;
14115 word internal_command;
14117 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14118 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14120 Info = GOOD;
14121 internal_command = plci->internal_command;
14122 plci->internal_command = 0;
14123 switch (internal_command)
14125 default:
14126 plci->command = 0;
14127 case FAX_CONNECT_ACK_COMMAND_1:
14128 if (plci_nl_busy (plci))
14130 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14131 return;
14133 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14134 plci->NData[0].P = plci->fax_connect_info_buffer;
14135 plci->NData[0].PLength = plci->fax_connect_info_length;
14136 plci->NL.X = plci->NData;
14137 plci->NL.ReqCh = 0;
14138 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14139 plci->adapter->request (&plci->NL);
14140 return;
14141 case FAX_CONNECT_ACK_COMMAND_2:
14142 if ((Rc != OK) && (Rc != OK_FC))
14144 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14145 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14146 break;
14149 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14150 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14152 if (plci->B3_prot == 4)
14153 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14154 else
14155 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14156 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14161 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14163 word Info;
14164 word internal_command;
14166 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14167 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14169 Info = GOOD;
14170 internal_command = plci->internal_command;
14171 plci->internal_command = 0;
14172 switch (internal_command)
14174 default:
14175 plci->command = 0;
14176 case FAX_EDATA_ACK_COMMAND_1:
14177 if (plci_nl_busy (plci))
14179 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14180 return;
14182 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14183 plci->NData[0].P = plci->fax_connect_info_buffer;
14184 plci->NData[0].PLength = plci->fax_edata_ack_length;
14185 plci->NL.X = plci->NData;
14186 plci->NL.ReqCh = 0;
14187 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14188 plci->adapter->request (&plci->NL);
14189 return;
14190 case FAX_EDATA_ACK_COMMAND_2:
14191 if ((Rc != OK) && (Rc != OK_FC))
14193 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14194 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14195 break;
14201 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14203 word Info;
14204 word internal_command;
14206 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14207 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14209 Info = GOOD;
14210 internal_command = plci->internal_command;
14211 plci->internal_command = 0;
14212 switch (internal_command)
14214 default:
14215 plci->command = 0;
14216 case FAX_CONNECT_INFO_COMMAND_1:
14217 if (plci_nl_busy (plci))
14219 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14220 return;
14222 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14223 plci->NData[0].P = plci->fax_connect_info_buffer;
14224 plci->NData[0].PLength = plci->fax_connect_info_length;
14225 plci->NL.X = plci->NData;
14226 plci->NL.ReqCh = 0;
14227 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14228 plci->adapter->request (&plci->NL);
14229 return;
14230 case FAX_CONNECT_INFO_COMMAND_2:
14231 if ((Rc != OK) && (Rc != OK_FC))
14233 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14234 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14235 Info = _WRONG_STATE;
14236 break;
14238 if (plci_nl_busy (plci))
14240 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14241 return;
14243 plci->command = _CONNECT_B3_R;
14244 nl_req_ncci (plci, N_CONNECT, 0);
14245 send_req (plci);
14246 return;
14248 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14252 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14254 word Info;
14255 word internal_command;
14257 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14258 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14260 Info = GOOD;
14261 internal_command = plci->internal_command;
14262 plci->internal_command = 0;
14263 switch (internal_command)
14265 default:
14266 plci->command = 0;
14267 plci->adjust_b_parms_msg = NULL;
14268 plci->adjust_b_facilities = plci->B1_facilities;
14269 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14270 plci->adjust_b_ncci = (word)(Id >> 16);
14271 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14272 plci->adjust_b_state = ADJUST_B_START;
14273 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14274 UnMapId (Id), (char *)(FILE_), __LINE__));
14275 case FAX_ADJUST_B23_COMMAND_1:
14276 Info = adjust_b_process (Id, plci, Rc);
14277 if (Info != GOOD)
14279 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14280 UnMapId (Id), (char *)(FILE_), __LINE__));
14281 break;
14283 if (plci->internal_command)
14284 return;
14285 case FAX_ADJUST_B23_COMMAND_2:
14286 if (plci_nl_busy (plci))
14288 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14289 return;
14291 plci->command = _CONNECT_B3_R;
14292 nl_req_ncci (plci, N_CONNECT, 0);
14293 send_req (plci);
14294 return;
14296 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14300 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14302 word internal_command;
14304 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14305 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14307 internal_command = plci->internal_command;
14308 plci->internal_command = 0;
14309 switch (internal_command)
14311 default:
14312 plci->command = 0;
14313 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14314 return;
14315 case FAX_DISCONNECT_COMMAND_1:
14316 case FAX_DISCONNECT_COMMAND_2:
14317 case FAX_DISCONNECT_COMMAND_3:
14318 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14320 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14321 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14322 break;
14324 if (Rc == OK)
14326 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14327 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14329 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14332 else if (Rc == 0)
14334 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14335 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14337 return;
14343 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14345 word Info;
14346 word internal_command;
14348 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14349 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14351 Info = GOOD;
14352 internal_command = plci->internal_command;
14353 plci->internal_command = 0;
14354 switch (internal_command)
14356 default:
14357 plci->command = 0;
14358 case RTP_CONNECT_B3_REQ_COMMAND_1:
14359 if (plci_nl_busy (plci))
14361 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14362 return;
14364 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14365 nl_req_ncci (plci, N_CONNECT, 0);
14366 send_req (plci);
14367 return;
14368 case RTP_CONNECT_B3_REQ_COMMAND_2:
14369 if ((Rc != OK) && (Rc != OK_FC))
14371 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14372 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14373 Info = _WRONG_STATE;
14374 break;
14376 if (plci_nl_busy (plci))
14378 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14379 return;
14381 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14382 plci->NData[0].PLength = plci->internal_req_buffer[0];
14383 plci->NData[0].P = plci->internal_req_buffer + 1;
14384 plci->NL.X = plci->NData;
14385 plci->NL.ReqCh = 0;
14386 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14387 plci->adapter->request (&plci->NL);
14388 break;
14389 case RTP_CONNECT_B3_REQ_COMMAND_3:
14390 return;
14392 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14396 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14398 word Info;
14399 word internal_command;
14401 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14402 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14404 Info = GOOD;
14405 internal_command = plci->internal_command;
14406 plci->internal_command = 0;
14407 switch (internal_command)
14409 default:
14410 plci->command = 0;
14411 case RTP_CONNECT_B3_RES_COMMAND_1:
14412 if (plci_nl_busy (plci))
14414 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14415 return;
14417 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14418 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14419 send_req (plci);
14420 return;
14421 case RTP_CONNECT_B3_RES_COMMAND_2:
14422 if ((Rc != OK) && (Rc != OK_FC))
14424 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14425 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14426 Info = _WRONG_STATE;
14427 break;
14429 if (plci_nl_busy (plci))
14431 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14432 return;
14434 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14435 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14436 plci->NData[0].PLength = plci->internal_req_buffer[0];
14437 plci->NData[0].P = plci->internal_req_buffer + 1;
14438 plci->NL.X = plci->NData;
14439 plci->NL.ReqCh = 0;
14440 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14441 plci->adapter->request (&plci->NL);
14442 return;
14443 case RTP_CONNECT_B3_RES_COMMAND_3:
14444 return;
14450 static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14452 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14453 word Info;
14454 word internal_command;
14456 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14457 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14459 Info = GOOD;
14460 internal_command = plci->internal_command;
14461 plci->internal_command = 0;
14462 switch (internal_command)
14464 default:
14465 if (!plci->NL.Id)
14466 break;
14467 plci->command = 0;
14468 plci->adjust_b_parms_msg = NULL;
14469 plci->adjust_b_facilities = plci->B1_facilities;
14470 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14471 plci->adjust_b_ncci = (word)(Id >> 16);
14472 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14473 plci->adjust_b_state = ADJUST_B_START;
14474 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14475 UnMapId (Id), (char *)(FILE_), __LINE__));
14476 case HOLD_SAVE_COMMAND_1:
14477 Info = adjust_b_process (Id, plci, Rc);
14478 if (Info != GOOD)
14480 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14481 UnMapId (Id), (char *)(FILE_), __LINE__));
14482 break;
14484 if (plci->internal_command)
14485 return;
14487 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14491 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14493 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14494 word Info;
14495 word internal_command;
14497 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14498 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14500 Info = GOOD;
14501 internal_command = plci->internal_command;
14502 plci->internal_command = 0;
14503 switch (internal_command)
14505 default:
14506 plci->command = 0;
14507 plci->adjust_b_parms_msg = NULL;
14508 plci->adjust_b_facilities = plci->B1_facilities;
14509 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14510 plci->adjust_b_ncci = (word)(Id >> 16);
14511 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14512 plci->adjust_b_state = ADJUST_B_START;
14513 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14514 UnMapId (Id), (char *)(FILE_), __LINE__));
14515 case RETRIEVE_RESTORE_COMMAND_1:
14516 Info = adjust_b_process (Id, plci, Rc);
14517 if (Info != GOOD)
14519 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14520 UnMapId (Id), (char *)(FILE_), __LINE__));
14521 break;
14523 if (plci->internal_command)
14524 return;
14526 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14530 static void init_b1_config (PLCI *plci)
14533 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14534 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14535 (char *)(FILE_), __LINE__));
14537 plci->B1_resource = 0;
14538 plci->B1_facilities = 0;
14540 plci->li_bchannel_id = 0;
14541 mixer_clear_config (plci);
14544 ec_clear_config (plci);
14547 dtmf_rec_clear_config (plci);
14548 dtmf_send_clear_config (plci);
14549 dtmf_parameter_clear_config (plci);
14551 adv_voice_clear_config (plci);
14552 adjust_b_clear (plci);
14556 static void clear_b1_config (PLCI *plci)
14559 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14560 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14561 (char *)(FILE_), __LINE__));
14563 adv_voice_clear_config (plci);
14564 adjust_b_clear (plci);
14566 ec_clear_config (plci);
14569 dtmf_rec_clear_config (plci);
14570 dtmf_send_clear_config (plci);
14571 dtmf_parameter_clear_config (plci);
14574 if ((plci->li_bchannel_id != 0)
14575 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14577 mixer_clear_config (plci);
14578 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14579 plci->li_bchannel_id = 0;
14582 plci->B1_resource = 0;
14583 plci->B1_facilities = 0;
14587 /* -----------------------------------------------------------------
14588 XON protocol local helpers
14589 ----------------------------------------------------------------- */
14590 static void channel_flow_control_remove (PLCI * plci) {
14591 DIVA_CAPI_ADAPTER * a = plci->adapter;
14592 word i;
14593 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14594 if (a->ch_flow_plci[i] == plci->Id) {
14595 a->ch_flow_plci[i] = 0;
14596 a->ch_flow_control[i] = 0;
14601 static void channel_x_on (PLCI * plci, byte ch) {
14602 DIVA_CAPI_ADAPTER * a = plci->adapter;
14603 if (a->ch_flow_control[ch] & N_XON_SENT) {
14604 a->ch_flow_control[ch] &= ~N_XON_SENT;
14608 static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14609 DIVA_CAPI_ADAPTER * a = plci->adapter;
14610 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14611 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14612 a->ch_flow_plci[ch] = plci->Id;
14613 a->ch_flow_control_pending++;
14617 static void channel_request_xon (PLCI * plci, byte ch) {
14618 DIVA_CAPI_ADAPTER * a = plci->adapter;
14620 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14621 a->ch_flow_control[ch] |= N_XON_REQ;
14622 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14623 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14627 static void channel_xmit_extended_xon (PLCI * plci) {
14628 DIVA_CAPI_ADAPTER * a;
14629 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14630 int i, one_requested = 0;
14632 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14633 return;
14636 for (i = 0; i < max_ch; i++) {
14637 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14638 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14639 (plci->Id == a->ch_flow_plci[i])) {
14640 channel_request_xon (plci, (byte)i);
14641 one_requested = 1;
14645 if (one_requested) {
14646 channel_xmit_xon (plci);
14651 Try to xmit next X_ON
14653 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14654 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14655 int i;
14657 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14658 return (0);
14661 if (a->last_flow_control_ch >= max_ch) {
14662 a->last_flow_control_ch = 1;
14664 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14665 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14666 (plci->Id == a->ch_flow_plci[i])) {
14667 a->last_flow_control_ch = i+1;
14668 return (i);
14672 for (i = 1; i < a->last_flow_control_ch; i++) {
14673 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14674 (plci->Id == a->ch_flow_plci[i])) {
14675 a->last_flow_control_ch = i+1;
14676 return (i);
14680 return (0);
14683 static void channel_xmit_xon (PLCI * plci) {
14684 DIVA_CAPI_ADAPTER * a = plci->adapter;
14685 byte ch;
14687 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14688 return;
14690 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14691 return;
14693 a->ch_flow_control[ch] &= ~N_XON_REQ;
14694 a->ch_flow_control[ch] |= N_XON_SENT;
14696 plci->NL.Req = plci->nl_req = (byte)N_XON;
14697 plci->NL.ReqCh = ch;
14698 plci->NL.X = plci->NData;
14699 plci->NL.XNum = 1;
14700 plci->NData[0].P = &plci->RBuffer[0];
14701 plci->NData[0].PLength = 0;
14703 plci->adapter->request(&plci->NL);
14706 static int channel_can_xon (PLCI * plci, byte ch) {
14707 APPL * APPLptr;
14708 DIVA_CAPI_ADAPTER * a;
14709 word NCCIcode;
14710 dword count;
14711 word Num;
14712 word i;
14714 APPLptr = plci->appl;
14715 a = plci->adapter;
14717 if (!APPLptr)
14718 return (0);
14720 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14722 /* count all buffers within the Application pool */
14723 /* belonging to the same NCCI. XON if a first is */
14724 /* used. */
14725 count = 0;
14726 Num = 0xffff;
14727 for(i=0; i<APPLptr->MaxBuffer; i++) {
14728 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14729 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14731 if ((count > 2) || (Num == 0xffff)) {
14732 return (0);
14734 return (1);
14738 /*------------------------------------------------------------------*/
14740 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14742 return 1;
14747 /**********************************************************************************/
14748 /* function groups the listening applications according to the CIP mask and the */
14749 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14750 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14751 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14752 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14753 /* OS specific part (per adapter). */
14754 /**********************************************************************************/
14755 static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14757 word i,j,k,busy,group_found;
14758 dword info_mask_group[MAX_CIP_TYPES];
14759 dword cip_mask_group[MAX_CIP_TYPES];
14760 word appl_number_group_type[MAX_APPL];
14761 PLCI *auxplci;
14763 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14765 if(!a->group_optimization_enabled)
14767 dbug(1,dprintf("No group optimization"));
14768 return;
14771 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14773 for(i=0;i<MAX_CIP_TYPES;i++)
14775 info_mask_group[i] = 0;
14776 cip_mask_group [i] = 0;
14778 for(i=0;i<MAX_APPL;i++)
14780 appl_number_group_type[i] = 0;
14782 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14783 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14784 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14786 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14787 return; /* allow good application unfiltered access */
14790 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14792 if(application[i].Id && a->CIP_Mask[i] )
14794 for(k=0,busy=false; k<a->max_plci; k++)
14796 if(a->plci[k].Id)
14798 auxplci = &a->plci[k];
14799 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14801 busy = true;
14802 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14804 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14806 busy = true;
14807 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14812 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14814 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14815 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14816 appl_number_group_type[i] = MAX_CIP_TYPES;
14817 group_found=true;
14818 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14820 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14821 { /* is group already present ? */
14822 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14823 group_found=true;
14824 dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14826 else if(!info_mask_group[j])
14827 { /* establish a new group */
14828 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14829 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14830 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14831 group_found=true;
14832 dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
14838 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14840 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14842 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14844 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14846 else
14848 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14849 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14851 if(appl_number_group_type[i] == appl_number_group_type[j])
14853 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14854 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14855 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14860 else /* application should not get a call */
14862 clear_group_ind_mask_bit (plci, i);
14870 /* OS notifies the driver about a application Capi_Register */
14871 word CapiRegister(word id)
14873 word i,j,appls_found;
14875 PLCI *plci;
14876 DIVA_CAPI_ADAPTER *a;
14878 for(i=0,appls_found=0; i<max_appl; i++)
14880 if( application[i].Id && (application[i].Id!=id) )
14882 appls_found++; /* an application has been found */
14886 if(appls_found) return true;
14887 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14889 a = &adapter[i];
14890 if(a->request)
14892 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14894 if(!appls_found) /* first application does a capi register */
14896 if((j=get_plci(a))) /* activate L1 of all adapters */
14898 plci = &a->plci[j-1];
14899 plci->command = 0;
14900 add_p(plci,OAD,"\x01\xfd");
14901 add_p(plci,CAI,"\x01\x80");
14902 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14903 add_p(plci,SHIFT|6,NULL);
14904 add_p(plci,SIN,"\x02\x00\x00");
14905 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14906 sig_req(plci,ASSIGN,DSIG_ID);
14907 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14908 sig_req(plci,SIG_CTRL,0);
14909 send_req(plci);
14915 return false;
14918 /*------------------------------------------------------------------*/
14920 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14922 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14924 word i;
14925 /* Format of vswitch_t:
14926 0 byte length
14927 1 byte VSWITCHIE
14928 2 byte VSWITCH_REQ/VSWITCH_IND
14929 3 byte reserved
14930 4 word VSwitchcommand
14931 6 word returnerror
14932 8... Params
14934 if(!plci ||
14935 !plci->appl ||
14936 !plci->State ||
14937 plci->Sig.Ind==NCR_FACILITY
14939 return;
14941 for(i=0;i<MAX_MULTI_IE;i++)
14943 if(!parms[i][0]) continue;
14944 if(parms[i][0]<7)
14946 parms[i][0]=0; /* kill it */
14947 continue;
14949 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14950 switch(parms[i][4])
14952 case VSJOIN:
14953 if(!plci->relatedPTYPLCI ||
14954 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14955 { /* Error */
14956 break;
14958 /* remember all necessary informations */
14959 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14961 break;
14963 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14964 { /* first indication after ECT-Request on Consultation Call */
14965 plci->vswitchstate=parms[i][9];
14966 parms[i][9]=2; /* State */
14967 /* now ask first Call to join */
14969 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14970 { /* Answer of VSWITCH_REQ from first Call */
14971 plci->vswitchstate=parms[i][9];
14972 /* tell consultation call to join
14973 and the protocol capabilities of the first call */
14975 else
14976 { /* Error */
14977 break;
14979 plci->vsprot=parms[i][10]; /* protocol */
14980 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14981 /* send join request to related PLCI */
14982 parms[i][1]=VSWITCHIE;
14983 parms[i][2]=VSWITCH_REQ;
14985 plci->relatedPTYPLCI->command = 0;
14986 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14987 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14988 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14989 send_req(plci->relatedPTYPLCI);
14990 break;
14991 case VSTRANSPORT:
14992 default:
14993 if(plci->relatedPTYPLCI &&
14994 plci->vswitchstate==3 &&
14995 plci->relatedPTYPLCI->vswitchstate==3)
14997 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14998 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14999 send_req(plci->relatedPTYPLCI);
15001 break;
15003 parms[i][0]=0; /* kill it */
15008 /*------------------------------------------------------------------*/
15010 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
15011 ENTITY e;
15012 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15014 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15015 return (-1);
15018 pReq->xdi_dma_descriptor_operation.Req = 0;
15019 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15021 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15022 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15023 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15024 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15026 e.user[0] = plci->adapter->Id - 1;
15027 plci->adapter->request((ENTITY*)pReq);
15029 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15030 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15031 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15032 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15033 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15034 plci->adapter->Id,
15035 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15036 *dma_magic));
15037 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15038 } else {
15039 dbug(1,dprintf("dma_alloc failed"));
15040 return (-1);
15044 static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15045 ENTITY e;
15046 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15048 if (nr < 0) {
15049 return;
15052 pReq->xdi_dma_descriptor_operation.Req = 0;
15053 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15055 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15056 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15057 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15058 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15060 e.user[0] = plci->adapter->Id - 1;
15061 plci->adapter->request((ENTITY*)pReq);
15063 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15064 dbug(1,dprintf("dma_free(%d)", nr));
15065 } else {
15066 dbug(1,dprintf("dma_free failed (%d)", nr));
15070 /*------------------------------------------------------------------*/