Linux 2.6.21
[linux/fpc-iii.git] / drivers / isdn / hardware / eicon / message.c
blob784232a144c8155d15cb4fa206c33a3ace9ebdaa
2 /*
4 Copyright (c) Eicon Networks, 2002.
6 This source file is supplied for the use with
7 Eicon Networks range of DIVA Server Adapters.
9 Eicon File Revision : 2.1
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #include "platform.h"
32 #include "di_defs.h"
33 #include "pc.h"
34 #include "capi20.h"
35 #include "divacapi.h"
36 #include "mdm_msg.h"
37 #include "divasync.h"
41 #define FILE_ "MESSAGE.C"
42 #define dprintf
52 /*------------------------------------------------------------------*/
53 /* This is options supported for all adapters that are server by */
54 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
55 /* and it is not necessary to save it separate for every adapter */
56 /* Macrose defined here have only local meaning */
57 /*------------------------------------------------------------------*/
58 static dword diva_xdi_extended_features = 0;
60 #define DIVA_CAPI_USE_CMA 0x00000001
61 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
62 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
63 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
66 CAPI can request to process all return codes self only if:
67 protocol code supports this && xdi supports this
69 #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))
71 /*------------------------------------------------------------------*/
72 /* local function prototypes */
73 /*------------------------------------------------------------------*/
75 static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci);
76 static void set_group_ind_mask (PLCI *plci);
77 static void clear_group_ind_mask_bit (PLCI *plci, word b);
78 static byte test_group_ind_mask_bit (PLCI *plci, word b);
79 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
80 word CapiRelease(word);
81 word CapiRegister(word);
82 word api_put(APPL *, CAPI_MSG *);
83 static word api_parse(byte *, word, byte *, API_PARSE *);
84 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
85 static void api_load_msg(API_SAVE *in, API_PARSE *out);
87 word api_remove_start(void);
88 void api_remove_complete(void);
90 static void plci_remove(PLCI *);
91 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a);
92 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
94 void callback(ENTITY *);
96 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
97 static void data_rc(PLCI *, byte);
98 static void data_ack(PLCI *, byte);
99 static void sig_ind(PLCI *);
100 static void SendInfo(PLCI *, dword, byte * *, byte);
101 static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte);
102 static void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms);
104 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
106 static void nl_ind(PLCI *);
108 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
133 static word get_plci(DIVA_CAPI_ADAPTER *);
134 static void add_p(PLCI *, byte, byte *);
135 static void add_s(PLCI * plci, byte code, API_PARSE * p);
136 static void add_ss(PLCI * plci, byte code, API_PARSE * p);
137 static void add_ie(PLCI * plci, byte code, byte * p, word p_length);
138 static void add_d(PLCI *, word, byte *);
139 static void add_ai(PLCI *, API_PARSE *);
140 static word add_b1(PLCI *, API_PARSE *, word, word);
141 static word add_b23(PLCI *, API_PARSE *);
142 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms);
143 static void sig_req(PLCI *, byte, byte);
144 static void nl_req_ncci(PLCI *, byte, byte);
145 static void send_req(PLCI *);
146 static void send_data(PLCI *);
147 static word plci_remove_check(PLCI *);
148 static void listen_check(DIVA_CAPI_ADAPTER *);
149 static byte AddInfo(byte **, byte **, byte *, byte *);
150 static byte getChannel(API_PARSE *);
151 static void IndParse(PLCI *, word *, byte **, byte);
152 static byte ie_compare(byte *, byte *);
153 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
154 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word);
157 XON protocol helpers
159 static void channel_flow_control_remove (PLCI * plci);
160 static void channel_x_off (PLCI * plci, byte ch, byte flag);
161 static void channel_x_on (PLCI * plci, byte ch);
162 static void channel_request_xon (PLCI * plci, byte ch);
163 static void channel_xmit_xon (PLCI * plci);
164 static int channel_can_xon (PLCI * plci, byte ch);
165 static void channel_xmit_extended_xon (PLCI * plci);
167 static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse);
168 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
169 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
170 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * );
171 static void VoiceChannelOff(PLCI *plci);
172 static void adv_voice_write_coefs (PLCI *plci, word write_command);
173 static void adv_voice_clear_config (PLCI *plci);
175 static word get_b1_facilities (PLCI * plci, byte b1_resource);
176 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities);
177 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities);
178 static word adjust_b_process (dword Id, PLCI *plci, byte Rc);
179 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
180 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc);
181 static void reset_b3_command (dword Id, PLCI *plci, byte Rc);
182 static void select_b_command (dword Id, PLCI *plci, byte Rc);
183 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc);
184 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc);
185 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc);
186 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc);
187 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc);
188 static void hold_save_command (dword Id, PLCI *plci, byte Rc);
189 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc);
190 static void init_b1_config (PLCI *plci);
191 static void clear_b1_config (PLCI *plci);
193 static void dtmf_command (dword Id, PLCI *plci, byte Rc);
194 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
195 static void dtmf_confirmation (dword Id, PLCI *plci);
196 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length);
197 static void dtmf_parameter_write (PLCI *plci);
200 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id);
201 static void mixer_set_bchannel_id (PLCI *plci, byte *chi);
202 static void mixer_clear_config (PLCI *plci);
203 static void mixer_notify_update (PLCI *plci, byte others);
204 static void mixer_command (dword Id, PLCI *plci, byte Rc);
205 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
206 static void mixer_indication_coefs_set (dword Id, PLCI *plci);
207 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length);
209 static void mixer_remove (PLCI *plci);
212 static void ec_command (dword Id, PLCI *plci, byte Rc);
213 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
214 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length);
217 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc);
218 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc);
221 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic);
222 static void diva_free_dma_descriptor (PLCI *plci, int nr);
224 /*------------------------------------------------------------------*/
225 /* external function prototypes */
226 /*------------------------------------------------------------------*/
228 extern byte MapController (byte);
229 extern byte UnMapController (byte);
230 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
231 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
233 void sendf(APPL *, word, dword, word, byte *, ...);
234 void * TransmitBufferSet(APPL * appl, dword ref);
235 void * TransmitBufferGet(APPL * appl, void * p);
236 void TransmitBufferFree(APPL * appl, void * p);
237 void * ReceiveBufferGet(APPL * appl, int Num);
239 int fax_head_line_time (char *buffer);
242 /*------------------------------------------------------------------*/
243 /* Global data definitions */
244 /*------------------------------------------------------------------*/
245 extern byte max_adapter;
246 extern byte max_appl;
247 extern DIVA_CAPI_ADAPTER * adapter;
248 extern APPL * application;
256 static byte remove_started = false;
257 static PLCI dummy_plci;
260 static struct _ftable {
261 word command;
262 byte * format;
263 byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
264 } ftable[] = {
265 {_DATA_B3_R, "dwww", data_b3_req},
266 {_DATA_B3_I|RESPONSE, "w", data_b3_res},
267 {_INFO_R, "ss", info_req},
268 {_INFO_I|RESPONSE, "", info_res},
269 {_CONNECT_R, "wsssssssss", connect_req},
270 {_CONNECT_I|RESPONSE, "wsssss", connect_res},
271 {_CONNECT_ACTIVE_I|RESPONSE, "", connect_a_res},
272 {_DISCONNECT_R, "s", disconnect_req},
273 {_DISCONNECT_I|RESPONSE, "", disconnect_res},
274 {_LISTEN_R, "dddss", listen_req},
275 {_ALERT_R, "s", alert_req},
276 {_FACILITY_R, "ws", facility_req},
277 {_FACILITY_I|RESPONSE, "ws", facility_res},
278 {_CONNECT_B3_R, "s", connect_b3_req},
279 {_CONNECT_B3_I|RESPONSE, "ws", connect_b3_res},
280 {_CONNECT_B3_ACTIVE_I|RESPONSE, "", connect_b3_a_res},
281 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
282 {_DISCONNECT_B3_I|RESPONSE, "", disconnect_b3_res},
283 {_RESET_B3_R, "s", reset_b3_req},
284 {_RESET_B3_I|RESPONSE, "", reset_b3_res},
285 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "ws", connect_b3_t90_a_res},
286 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "", connect_b3_t90_a_res},
287 {_SELECT_B_REQ, "s", select_b_req},
288 {_MANUFACTURER_R, "dws", manufacturer_req},
289 {_MANUFACTURER_I|RESPONSE, "dws", manufacturer_res},
290 {_MANUFACTURER_I|RESPONSE, "", manufacturer_res}
293 static byte * cip_bc[29][2] = {
294 { "", "" }, /* 0 */
295 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
296 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
297 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
298 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
299 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
300 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
301 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
302 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
303 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
304 { "", "" }, /* 10 */
305 { "", "" }, /* 11 */
306 { "", "" }, /* 12 */
307 { "", "" }, /* 13 */
308 { "", "" }, /* 14 */
309 { "", "" }, /* 15 */
311 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
312 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
313 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
320 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
321 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
322 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
323 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
326 static byte * cip_hlc[29] = {
327 "", /* 0 */
328 "", /* 1 */
329 "", /* 2 */
330 "", /* 3 */
331 "", /* 4 */
332 "", /* 5 */
333 "", /* 6 */
334 "", /* 7 */
335 "", /* 8 */
336 "", /* 9 */
337 "", /* 10 */
338 "", /* 11 */
339 "", /* 12 */
340 "", /* 13 */
341 "", /* 14 */
342 "", /* 15 */
344 "\x02\x91\x81", /* 16 */
345 "\x02\x91\x84", /* 17 */
346 "\x02\x91\xa1", /* 18 */
347 "\x02\x91\xa4", /* 19 */
348 "\x02\x91\xa8", /* 20 */
349 "\x02\x91\xb1", /* 21 */
350 "\x02\x91\xb2", /* 22 */
351 "\x02\x91\xb5", /* 23 */
352 "\x02\x91\xb8", /* 24 */
353 "\x02\x91\xc1", /* 25 */
354 "\x02\x91\x81", /* 26 */
355 "\x03\x91\xe0\x01", /* 27 */
356 "\x03\x91\xe0\x02" /* 28 */
359 /*------------------------------------------------------------------*/
361 #define V120_HEADER_LENGTH 1
362 #define V120_HEADER_EXTEND_BIT 0x80
363 #define V120_HEADER_BREAK_BIT 0x40
364 #define V120_HEADER_C1_BIT 0x04
365 #define V120_HEADER_C2_BIT 0x08
366 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
368 static byte v120_default_header[] =
371 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
375 static byte v120_break_header[] =
378 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
383 /*------------------------------------------------------------------*/
384 /* API_PUT function */
385 /*------------------------------------------------------------------*/
387 word api_put(APPL * appl, CAPI_MSG * msg)
389 word i, j, k, l, n;
390 word ret;
391 byte c;
392 byte controller;
393 DIVA_CAPI_ADAPTER * a;
394 PLCI * plci;
395 NCCI * ncci_ptr;
396 word ncci;
397 CAPI_MSG *m;
398 API_PARSE msg_parms[MAX_MSG_PARMS+1];
400 if (msg->header.length < sizeof (msg->header) ||
401 msg->header.length > MAX_MSG_SIZE) {
402 dbug(1,dprintf("bad len"));
403 return _BAD_MSG;
406 controller = (byte)((msg->header.controller &0x7f)-1);
408 /* controller starts with 0 up to (max_adapter - 1) */
409 if ( controller >= max_adapter )
411 dbug(1,dprintf("invalid ctrl"));
412 return _BAD_MSG;
415 a = &adapter[controller];
416 plci = NULL;
417 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
419 dbug(1,dprintf("plci=%x",msg->header.plci));
420 plci = &a->plci[msg->header.plci-1];
421 ncci = GET_WORD(&msg->header.ncci);
422 if (plci->Id
423 && (plci->appl
424 || (plci->State == INC_CON_PENDING)
425 || (plci->State == INC_CON_ALERT)
426 || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
427 && ((ncci == 0)
428 || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
429 || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
431 i = plci->msg_in_read_pos;
432 j = plci->msg_in_write_pos;
433 if (j >= i)
435 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
436 i += MSG_IN_QUEUE_SIZE - j;
437 else
438 j = 0;
440 else
443 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
445 if (i > MSG_IN_QUEUE_SIZE - n)
446 i = MSG_IN_QUEUE_SIZE - n + 1;
447 i -= j;
450 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
453 dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
454 msg->header.length, plci->msg_in_write_pos,
455 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
457 return _QUEUE_FULL;
459 c = false;
460 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
461 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
463 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
464 c = true;
466 if (msg->header.command == _DATA_B3_R)
468 if (msg->header.length < 20)
470 dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
471 return _BAD_MSG;
473 ncci_ptr = &(a->ncci[ncci]);
474 n = ncci_ptr->data_pending;
475 l = ncci_ptr->data_ack_pending;
476 k = plci->msg_in_read_pos;
477 while (k != plci->msg_in_write_pos)
479 if (k == plci->msg_in_wrap_pos)
480 k = 0;
481 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
482 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
484 n++;
485 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
486 l++;
489 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
490 MSG_IN_OVERHEAD + 3) & 0xfffc;
493 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
495 dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
496 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
498 return _QUEUE_FULL;
500 if (plci->req_in || plci->internal_command)
502 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
503 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
505 dbug(0,dprintf("Q-FULL3(requeue)"));
507 return _QUEUE_FULL;
509 c = true;
512 else
514 if (plci->req_in || plci->internal_command)
515 c = true;
516 else
518 plci->command = msg->header.command;
519 plci->number = msg->header.number;
522 if (c)
524 dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
525 msg->header.command, plci->req_in, plci->internal_command,
526 msg->header.length, plci->msg_in_write_pos,
527 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
528 if (j == 0)
529 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
530 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
531 for (i = 0; i < msg->header.length; i++)
532 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
533 if (m->header.command == _DATA_B3_R)
536 m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
540 j = (j + 3) & 0xfffc;
542 *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl;
543 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
544 return 0;
547 else
549 plci = NULL;
552 dbug(1,dprintf("com=%x",msg->header.command));
554 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
555 for(i=0, ret = _BAD_MSG;
556 i<(sizeof(ftable)/sizeof(struct _ftable));
557 i++) {
559 if(ftable[i].command==msg->header.command) {
560 /* break loop if the message is correct, otherwise continue scan */
561 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
562 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
563 ret = 0;
564 break;
566 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
569 if(ret) {
570 dbug(1,dprintf("BAD_MSG"));
571 if(plci) plci->command = 0;
572 return ret;
576 c = ftable[i].function(GET_DWORD(&msg->header.controller),
577 msg->header.number,
579 plci,
580 appl,
581 msg_parms);
583 channel_xmit_extended_xon (plci);
585 if(c==1) send_req(plci);
586 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
587 if(plci && !plci->req_in) plci->command = 0;
588 return 0;
592 /*------------------------------------------------------------------*/
593 /* api_parse function, check the format of api messages */
594 /*------------------------------------------------------------------*/
596 word api_parse(byte * msg, word length, byte * format, API_PARSE * parms)
598 word i;
599 word p;
601 for(i=0,p=0; format[i]; i++) {
602 if(parms)
604 parms[i].info = &msg[p];
606 switch(format[i]) {
607 case 'b':
608 p +=1;
609 break;
610 case 'w':
611 p +=2;
612 break;
613 case 'd':
614 p +=4;
615 break;
616 case 's':
617 if(msg[p]==0xff) {
618 parms[i].info +=2;
619 parms[i].length = msg[p+1] + (msg[p+2]<<8);
620 p +=(parms[i].length +3);
622 else {
623 parms[i].length = msg[p];
624 p +=(parms[i].length +1);
626 break;
629 if(p>length) return true;
631 if(parms) parms[i].info = NULL;
632 return false;
635 void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
637 word i, j, n = 0;
638 byte *p;
640 p = out->info;
641 for (i = 0; format[i] != '\0'; i++)
643 out->parms[i].info = p;
644 out->parms[i].length = in[i].length;
645 switch (format[i])
647 case 'b':
648 n = 1;
649 break;
650 case 'w':
651 n = 2;
652 break;
653 case 'd':
654 n = 4;
655 break;
656 case 's':
657 n = in[i].length + 1;
658 break;
660 for (j = 0; j < n; j++)
661 *(p++) = in[i].info[j];
663 out->parms[i].info = NULL;
664 out->parms[i].length = 0;
667 void api_load_msg(API_SAVE *in, API_PARSE *out)
669 word i;
671 i = 0;
674 out[i].info = in->parms[i].info;
675 out[i].length = in->parms[i].length;
676 } while (in->parms[i++].info);
680 /*------------------------------------------------------------------*/
681 /* CAPI remove function */
682 /*------------------------------------------------------------------*/
684 word api_remove_start(void)
686 word i;
687 word j;
689 if(!remove_started) {
690 remove_started = true;
691 for(i=0;i<max_adapter;i++) {
692 if(adapter[i].request) {
693 for(j=0;j<adapter[i].max_plci;j++) {
694 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
698 return 1;
700 else {
701 for(i=0;i<max_adapter;i++) {
702 if(adapter[i].request) {
703 for(j=0;j<adapter[i].max_plci;j++) {
704 if(adapter[i].plci[j].Sig.Id) return 1;
709 api_remove_complete();
710 return 0;
714 /*------------------------------------------------------------------*/
715 /* internal command queue */
716 /*------------------------------------------------------------------*/
718 static void init_internal_command_queue (PLCI *plci)
720 word i;
722 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
723 (char *)(FILE_), __LINE__));
725 plci->internal_command = 0;
726 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
727 plci->internal_command_queue[i] = NULL;
731 static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
733 word i;
735 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
736 UnMapId (Id), (char *)(FILE_), __LINE__));
738 if (plci->internal_command == 0)
740 plci->internal_command_queue[0] = command_function;
741 (* command_function)(Id, plci, OK);
743 else
745 i = 1;
746 while (plci->internal_command_queue[i] != 0)
747 i++;
748 plci->internal_command_queue[i] = command_function;
753 static void next_internal_command (dword Id, PLCI *plci)
755 word i;
757 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
758 UnMapId (Id), (char *)(FILE_), __LINE__));
760 plci->internal_command = 0;
761 plci->internal_command_queue[0] = NULL;
762 while (plci->internal_command_queue[1] != 0)
764 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
765 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
766 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
767 (*(plci->internal_command_queue[0]))(Id, plci, OK);
768 if (plci->internal_command != 0)
769 return;
770 plci->internal_command_queue[0] = NULL;
775 /*------------------------------------------------------------------*/
776 /* NCCI allocate/remove function */
777 /*------------------------------------------------------------------*/
779 static dword ncci_mapping_bug = 0;
781 static word get_ncci (PLCI *plci, byte ch, word force_ncci)
783 DIVA_CAPI_ADAPTER *a;
784 word ncci, i, j, k;
786 a = plci->adapter;
787 if (!ch || a->ch_ncci[ch])
789 ncci_mapping_bug++;
790 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
791 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
792 ncci = ch;
794 else
796 if (force_ncci)
797 ncci = force_ncci;
798 else
800 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
801 ncci = ch;
802 else
804 ncci = 1;
805 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
806 ncci++;
807 if (ncci == MAX_NCCI+1)
809 ncci_mapping_bug++;
810 i = 1;
813 j = 1;
814 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
815 j++;
816 k = j;
817 if (j < MAX_NCCI+1)
821 j++;
822 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
824 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
825 if (i < MAX_NL_CHANNEL+1)
827 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
828 ncci_mapping_bug, ch, force_ncci, i, k, j));
830 else
832 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
833 ncci_mapping_bug, ch, force_ncci));
835 ncci = ch;
838 a->ncci_plci[ncci] = plci->Id;
839 a->ncci_state[ncci] = IDLE;
840 if (!plci->ncci_ring_list)
841 plci->ncci_ring_list = ncci;
842 else
843 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
844 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
846 a->ncci_ch[ncci] = ch;
847 a->ch_ncci[ch] = (byte) ncci;
848 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
849 ncci_mapping_bug, ch, force_ncci, ch, ncci));
851 return (ncci);
855 static void ncci_free_receive_buffers (PLCI *plci, word ncci)
857 DIVA_CAPI_ADAPTER *a;
858 APPL *appl;
859 word i, ncci_code;
860 dword Id;
862 a = plci->adapter;
863 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
864 if (ncci)
866 if (a->ncci_plci[ncci] == plci->Id)
868 if (!plci->appl)
870 ncci_mapping_bug++;
871 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
872 ncci_mapping_bug, Id));
874 else
876 appl = plci->appl;
877 ncci_code = ncci | (((word) a->Id) << 8);
878 for (i = 0; i < appl->MaxBuffer; i++)
880 if ((appl->DataNCCI[i] == ncci_code)
881 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
883 appl->DataNCCI[i] = 0;
889 else
891 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
893 if (a->ncci_plci[ncci] == plci->Id)
895 if (!plci->appl)
897 ncci_mapping_bug++;
898 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
899 ncci_mapping_bug, Id));
901 else
903 appl = plci->appl;
904 ncci_code = ncci | (((word) a->Id) << 8);
905 for (i = 0; i < appl->MaxBuffer; i++)
907 if ((appl->DataNCCI[i] == ncci_code)
908 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
910 appl->DataNCCI[i] = 0;
920 static void cleanup_ncci_data (PLCI *plci, word ncci)
922 NCCI *ncci_ptr;
924 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
926 ncci_ptr = &(plci->adapter->ncci[ncci]);
927 if (plci->appl)
929 while (ncci_ptr->data_pending != 0)
931 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
932 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
933 (ncci_ptr->data_out)++;
934 if (ncci_ptr->data_out == MAX_DATA_B3)
935 ncci_ptr->data_out = 0;
936 (ncci_ptr->data_pending)--;
939 ncci_ptr->data_out = 0;
940 ncci_ptr->data_pending = 0;
941 ncci_ptr->data_ack_out = 0;
942 ncci_ptr->data_ack_pending = 0;
947 static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
949 DIVA_CAPI_ADAPTER *a;
950 dword Id;
951 word i;
953 a = plci->adapter;
954 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
955 if (!preserve_ncci)
956 ncci_free_receive_buffers (plci, ncci);
957 if (ncci)
959 if (a->ncci_plci[ncci] != plci->Id)
961 ncci_mapping_bug++;
962 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
963 ncci_mapping_bug, Id, preserve_ncci));
965 else
967 cleanup_ncci_data (plci, ncci);
968 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
969 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
970 a->ch_ncci[a->ncci_ch[ncci]] = 0;
971 if (!preserve_ncci)
973 a->ncci_ch[ncci] = 0;
974 a->ncci_plci[ncci] = 0;
975 a->ncci_state[ncci] = IDLE;
976 i = plci->ncci_ring_list;
977 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
978 i = a->ncci_next[i];
979 if ((i != 0) && (a->ncci_next[i] == ncci))
981 if (i == ncci)
982 plci->ncci_ring_list = 0;
983 else if (plci->ncci_ring_list == ncci)
984 plci->ncci_ring_list = i;
985 a->ncci_next[i] = a->ncci_next[ncci];
987 a->ncci_next[ncci] = 0;
991 else
993 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
995 if (a->ncci_plci[ncci] == plci->Id)
997 cleanup_ncci_data (plci, ncci);
998 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
999 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
1000 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1001 if (!preserve_ncci)
1003 a->ncci_ch[ncci] = 0;
1004 a->ncci_plci[ncci] = 0;
1005 a->ncci_state[ncci] = IDLE;
1006 a->ncci_next[ncci] = 0;
1010 if (!preserve_ncci)
1011 plci->ncci_ring_list = 0;
1016 /*------------------------------------------------------------------*/
1017 /* PLCI remove function */
1018 /*------------------------------------------------------------------*/
1020 static void plci_free_msg_in_queue (PLCI *plci)
1022 word i;
1024 if (plci->appl)
1026 i = plci->msg_in_read_pos;
1027 while (i != plci->msg_in_write_pos)
1029 if (i == plci->msg_in_wrap_pos)
1030 i = 0;
1031 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1034 TransmitBufferFree (plci->appl,
1035 (byte *)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1039 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1040 MSG_IN_OVERHEAD + 3) & 0xfffc;
1044 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1045 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1046 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1050 static void plci_remove(PLCI * plci)
1053 if(!plci) {
1054 dbug(1,dprintf("plci_remove(no plci)"));
1055 return;
1057 init_internal_command_queue (plci);
1058 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1059 if(plci_remove_check(plci))
1061 return;
1063 if (plci->Sig.Id == 0xff)
1065 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1066 if (plci->NL.Id && !plci->nl_remove_id)
1068 nl_req_ncci(plci,REMOVE,0);
1069 send_req(plci);
1072 else
1074 if (!plci->sig_remove_id
1075 && (plci->Sig.Id
1076 || (plci->req_in!=plci->req_out)
1077 || (plci->nl_req || plci->sig_req)))
1079 sig_req(plci,HANGUP,0);
1080 send_req(plci);
1083 ncci_remove (plci, 0, false);
1084 plci_free_msg_in_queue (plci);
1086 plci->channels = 0;
1087 plci->appl = NULL;
1088 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1089 plci->State = OUTG_DIS_PENDING;
1092 /*------------------------------------------------------------------*/
1093 /* Application Group function helpers */
1094 /*------------------------------------------------------------------*/
1096 static void set_group_ind_mask (PLCI *plci)
1098 word i;
1100 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1101 plci->group_optimization_mask_table[i] = 0xffffffffL;
1104 static void clear_group_ind_mask_bit (PLCI *plci, word b)
1106 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1109 static byte test_group_ind_mask_bit (PLCI *plci, word b)
1111 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1114 /*------------------------------------------------------------------*/
1115 /* c_ind_mask operations for arbitrary MAX_APPL */
1116 /*------------------------------------------------------------------*/
1118 static void clear_c_ind_mask (PLCI *plci)
1120 word i;
1122 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1123 plci->c_ind_mask_table[i] = 0;
1126 static byte c_ind_mask_empty (PLCI *plci)
1128 word i;
1130 i = 0;
1131 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1132 i++;
1133 return (i == C_IND_MASK_DWORDS);
1136 static void set_c_ind_mask_bit (PLCI *plci, word b)
1138 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1141 static void clear_c_ind_mask_bit (PLCI *plci, word b)
1143 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1146 static byte test_c_ind_mask_bit (PLCI *plci, word b)
1148 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1151 static void dump_c_ind_mask (PLCI *plci)
1153 static char hex_digit_table[0x10] =
1154 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1155 word i, j, k;
1156 dword d;
1157 char *p;
1158 char buf[40];
1160 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1162 p = buf + 36;
1163 *p = '\0';
1164 for (j = 0; j < 4; j++)
1166 if (i+j < C_IND_MASK_DWORDS)
1168 d = plci->c_ind_mask_table[i+j];
1169 for (k = 0; k < 8; k++)
1171 *(--p) = hex_digit_table[d & 0xf];
1172 d >>= 4;
1175 else if (i != 0)
1177 for (k = 0; k < 8; k++)
1178 *(--p) = ' ';
1180 *(--p) = ' ';
1182 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1190 #define dump_plcis(a)
1194 /*------------------------------------------------------------------*/
1195 /* translation function for each message */
1196 /*------------------------------------------------------------------*/
1198 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1200 word ch;
1201 word i;
1202 word Info;
1203 word CIP;
1204 byte LinkLayer;
1205 API_PARSE * ai;
1206 API_PARSE * bp;
1207 API_PARSE ai_parms[5];
1208 word channel = 0;
1209 dword ch_mask;
1210 byte m;
1211 static byte esc_chi[35] = {0x02,0x18,0x01};
1212 static byte lli[2] = {0x01,0x00};
1213 byte noCh = 0;
1214 word dir = 0;
1215 byte *p_chi = "";
1217 for(i=0;i<5;i++) ai_parms[i].length = 0;
1219 dbug(1,dprintf("connect_req(%d)",parms->length));
1220 Info = _WRONG_IDENTIFIER;
1221 if(a)
1223 if(a->adapter_disabled)
1225 dbug(1,dprintf("adapter disabled"));
1226 Id = ((word)1<<8)|a->Id;
1227 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1228 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1229 return false;
1231 Info = _OUT_OF_PLCI;
1232 if((i=get_plci(a)))
1234 Info = 0;
1235 plci = &a->plci[i-1];
1236 plci->appl = appl;
1237 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1238 /* check 'external controller' bit for codec support */
1239 if(Id & EXT_CONTROLLER)
1241 if(AdvCodecSupport(a, plci, appl, 0) )
1243 plci->Id = 0;
1244 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1245 return 2;
1248 ai = &parms[9];
1249 bp = &parms[5];
1250 ch = 0;
1251 if(bp->length)LinkLayer = bp->info[3];
1252 else LinkLayer = 0;
1253 if(ai->length)
1255 ch=0xffff;
1256 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1258 ch = 0;
1259 if(ai_parms[0].length)
1261 ch = GET_WORD(ai_parms[0].info+1);
1262 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1263 if(ch==4) /* explizit CHI in message */
1265 /* check length of B-CH struct */
1266 if((ai_parms[0].info)[3]>=1)
1268 if((ai_parms[0].info)[4]==CHI)
1270 p_chi = &((ai_parms[0].info)[5]);
1272 else
1274 p_chi = &((ai_parms[0].info)[3]);
1276 if(p_chi[0]>35) /* check length of channel ID */
1278 Info = _WRONG_MESSAGE_FORMAT;
1281 else Info = _WRONG_MESSAGE_FORMAT;
1284 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1286 dir = GET_WORD(ai_parms[0].info+3);
1287 ch_mask = 0;
1288 m = 0x3f;
1289 for(i=0; i+5<=ai_parms[0].length; i++)
1291 if(ai_parms[0].info[i+5]!=0)
1293 if((ai_parms[0].info[i+5] | m) != 0xff)
1294 Info = _WRONG_MESSAGE_FORMAT;
1295 else
1297 if (ch_mask == 0)
1298 channel = i;
1299 ch_mask |= 1L << i;
1302 m = 0;
1304 if (ch_mask == 0)
1305 Info = _WRONG_MESSAGE_FORMAT;
1306 if (!Info)
1308 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1310 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1311 for(i=0; i+5<=ai_parms[0].length; i++)
1312 esc_chi[i+3] = ai_parms[0].info[i+5];
1314 else
1315 esc_chi[0] = 2;
1316 esc_chi[2] = (byte)channel;
1317 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1318 add_p(plci,LLI,lli);
1319 add_p(plci,ESC,esc_chi);
1320 plci->State = LOCAL_CONNECT;
1321 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1326 else Info = _WRONG_MESSAGE_FORMAT;
1329 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1330 plci->command = _CONNECT_R;
1331 plci->number = Number;
1332 /* x.31 or D-ch free SAPI in LinkLayer? */
1333 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1334 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1336 /* B-channel used for B3 connections (ch==0), or no B channel */
1337 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1338 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1339 else Info = add_b1(plci,&parms[5],ch,0);
1340 add_s(plci,OAD,&parms[2]);
1341 add_s(plci,OSA,&parms[4]);
1342 add_s(plci,BC,&parms[6]);
1343 add_s(plci,LLC,&parms[7]);
1344 add_s(plci,HLC,&parms[8]);
1345 CIP = GET_WORD(parms[0].info);
1346 if (a->Info_Mask[appl->Id-1] & 0x200)
1348 /* early B3 connect (CIP mask bit 9) no release after a disc */
1349 add_p(plci,LLI,"\x01\x01");
1351 if(GET_WORD(parms[0].info)<29) {
1352 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1353 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1355 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1356 sig_req(plci,ASSIGN,DSIG_ID);
1358 else if(ch==1) {
1360 /* D-Channel used for B3 connections */
1361 plci->Sig.Id = 0xff;
1362 Info = 0;
1365 if(!Info && ch!=2 && !noCh ) {
1366 Info = add_b23(plci,&parms[5]);
1367 if(!Info) {
1368 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1372 if(!Info)
1374 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1376 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1378 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1379 plci->spoofed_msg = CALL_REQ;
1380 plci->internal_command = BLOCK_PLCI;
1381 plci->command = 0;
1382 dbug(1,dprintf("Spoof"));
1383 send_req(plci);
1384 return false;
1386 if(ch==4)add_p(plci,CHI,p_chi);
1387 add_s(plci,CPN,&parms[1]);
1388 add_s(plci,DSA,&parms[3]);
1389 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1390 add_ai(plci,&parms[9]);
1391 if(!dir)sig_req(plci,CALL_REQ,0);
1392 else
1394 plci->command = PERM_LIST_REQ;
1395 plci->appl = appl;
1396 sig_req(plci,LISTEN_REQ,0);
1397 send_req(plci);
1398 return false;
1401 send_req(plci);
1402 return false;
1404 plci->Id = 0;
1407 sendf(appl,
1408 _CONNECT_R|CONFIRM,
1410 Number,
1411 "w",Info);
1412 return 2;
1415 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1417 word i, Info;
1418 word Reject;
1419 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1420 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1421 API_PARSE * ai;
1422 API_PARSE ai_parms[5];
1423 word ch=0;
1425 if(!plci) {
1426 dbug(1,dprintf("connect_res(no plci)"));
1427 return 0; /* no plci, no send */
1430 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1431 for(i=0;i<5;i++) ai_parms[i].length = 0;
1432 ai = &parms[5];
1433 dbug(1,dprintf("ai->length=%d",ai->length));
1435 if(ai->length)
1437 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1439 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1440 ch = 0;
1441 if(ai_parms[0].length)
1443 ch = GET_WORD(ai_parms[0].info+1);
1444 dbug(1,dprintf("BCH-I=0x%x",ch));
1449 if(plci->State==INC_CON_CONNECTED_ALERT)
1451 dbug(1,dprintf("Connected Alert Call_Res"));
1452 if (a->Info_Mask[appl->Id-1] & 0x200)
1454 /* early B3 connect (CIP mask bit 9) no release after a disc */
1455 add_p(plci,LLI,"\x01\x01");
1457 add_s(plci, CONN_NR, &parms[2]);
1458 add_s(plci, LLC, &parms[4]);
1459 add_ai(plci, &parms[5]);
1460 plci->State = INC_CON_ACCEPT;
1461 sig_req(plci, CALL_RES,0);
1462 return 1;
1464 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1465 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1466 dump_c_ind_mask (plci);
1467 Reject = GET_WORD(parms[0].info);
1468 dbug(1,dprintf("Reject=0x%x",Reject));
1469 if(Reject)
1471 if(c_ind_mask_empty (plci))
1473 if((Reject&0xff00)==0x3400)
1475 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1476 add_p(plci,ESC,esc_t);
1477 add_ai(plci, &parms[5]);
1478 sig_req(plci,REJECT,0);
1480 else if(Reject==1 || Reject>9)
1482 add_ai(plci, &parms[5]);
1483 sig_req(plci,HANGUP,0);
1485 else
1487 esc_t[2] = cau_t[(Reject&0x000f)];
1488 add_p(plci,ESC,esc_t);
1489 add_ai(plci, &parms[5]);
1490 sig_req(plci,REJECT,0);
1492 plci->appl = appl;
1494 else
1496 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1499 else {
1500 plci->appl = appl;
1501 if(Id & EXT_CONTROLLER){
1502 if(AdvCodecSupport(a, plci, appl, 0)){
1503 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1504 sig_req(plci,HANGUP,0);
1505 return 1;
1507 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1509 Info = add_b23(plci, &parms[1]);
1510 if (Info)
1512 dbug(1,dprintf("connect_res(error from add_b23)"));
1513 sig_req(plci,HANGUP,0);
1514 return 1;
1516 if(plci->adv_nl)
1518 nl_req_ncci(plci, ASSIGN, 0);
1522 else
1524 plci->tel = 0;
1525 if(ch!=2)
1527 Info = add_b23(plci, &parms[1]);
1528 if (Info)
1530 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1531 sig_req(plci,HANGUP,0);
1532 return 1;
1535 nl_req_ncci(plci, ASSIGN, 0);
1538 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1540 api_save_msg(parms, "wsssss", &plci->saved_msg);
1541 plci->spoofed_msg = CALL_RES;
1542 plci->internal_command = BLOCK_PLCI;
1543 plci->command = 0;
1544 dbug(1,dprintf("Spoof"));
1546 else
1548 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1549 if (a->Info_Mask[appl->Id-1] & 0x200)
1551 /* early B3 connect (CIP mask bit 9) no release after a disc */
1552 add_p(plci,LLI,"\x01\x01");
1554 add_s(plci, CONN_NR, &parms[2]);
1555 add_s(plci, LLC, &parms[4]);
1556 add_ai(plci, &parms[5]);
1557 plci->State = INC_CON_ACCEPT;
1558 sig_req(plci, CALL_RES,0);
1561 for(i=0; i<max_appl; i++) {
1562 if(test_c_ind_mask_bit (plci, i)) {
1563 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1568 return 1;
1571 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1573 dbug(1,dprintf("connect_a_res"));
1574 return false;
1577 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1579 word Info;
1580 word i;
1582 dbug(1,dprintf("disconnect_req"));
1584 Info = _WRONG_IDENTIFIER;
1586 if(plci)
1588 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1590 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1591 plci->appl = appl;
1592 for(i=0; i<max_appl; i++)
1594 if(test_c_ind_mask_bit (plci, i))
1595 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1597 plci->State = OUTG_DIS_PENDING;
1599 if(plci->Sig.Id && plci->appl)
1601 Info = 0;
1602 if(plci->Sig.Id!=0xff)
1604 if(plci->State!=INC_DIS_PENDING)
1606 add_ai(plci, &msg[0]);
1607 sig_req(plci,HANGUP,0);
1608 plci->State = OUTG_DIS_PENDING;
1609 return 1;
1612 else
1614 if (plci->NL.Id && !plci->nl_remove_id)
1616 mixer_remove (plci);
1617 nl_req_ncci(plci,REMOVE,0);
1618 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1619 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1620 plci->State = INC_DIS_PENDING;
1622 return 1;
1627 if(!appl) return false;
1628 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1629 return false;
1632 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1634 dbug(1,dprintf("disconnect_res"));
1635 if(plci)
1637 /* clear ind mask bit, just in case of collsion of */
1638 /* DISCONNECT_IND and CONNECT_RES */
1639 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1640 ncci_free_receive_buffers (plci, 0);
1641 if(plci_remove_check(plci))
1643 return 0;
1645 if(plci->State==INC_DIS_PENDING
1646 || plci->State==SUSPENDING) {
1647 if(c_ind_mask_empty (plci)) {
1648 if(plci->State!=SUSPENDING)plci->State = IDLE;
1649 dbug(1,dprintf("chs=%d",plci->channels));
1650 if(!plci->channels) {
1651 plci_remove(plci);
1656 return 0;
1659 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1661 word Info;
1662 byte i;
1664 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1666 Info = _WRONG_IDENTIFIER;
1667 if(a) {
1668 Info = 0;
1669 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1670 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1671 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1672 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1673 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1676 /* check if external controller listen and switch listen on or off*/
1677 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1678 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1679 dummy_plci.State = IDLE;
1680 a->codec_listen[appl->Id-1] = &dummy_plci;
1681 a->TelOAD[0] = (byte)(parms[3].length);
1682 for(i=1;parms[3].length>=i && i<22;i++) {
1683 a->TelOAD[i] = parms[3].info[i];
1685 a->TelOAD[i] = 0;
1686 a->TelOSA[0] = (byte)(parms[4].length);
1687 for(i=1;parms[4].length>=i && i<22;i++) {
1688 a->TelOSA[i] = parms[4].info[i];
1690 a->TelOSA[i] = 0;
1692 else Info = 0x2002; /* wrong controller, codec not supported */
1694 else{ /* clear listen */
1695 a->codec_listen[appl->Id-1] = (PLCI *)0;
1698 sendf(appl,
1699 _LISTEN_R|CONFIRM,
1701 Number,
1702 "w",Info);
1704 if (a) listen_check(a);
1705 return false;
1708 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1710 word i;
1711 API_PARSE * ai;
1712 PLCI * rc_plci = NULL;
1713 API_PARSE ai_parms[5];
1714 word Info = 0;
1716 dbug(1,dprintf("info_req"));
1717 for(i=0;i<5;i++) ai_parms[i].length = 0;
1719 ai = &msg[1];
1721 if(ai->length)
1723 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1725 dbug(1,dprintf("AddInfo wrong"));
1726 Info = _WRONG_MESSAGE_FORMAT;
1729 if(!a) Info = _WRONG_STATE;
1731 if(!Info && plci)
1732 { /* no fac, with CPN, or KEY */
1733 rc_plci = plci;
1734 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1736 /* overlap sending option */
1737 dbug(1,dprintf("OvlSnd"));
1738 add_s(plci,CPN,&msg[0]);
1739 add_s(plci,KEY,&ai_parms[1]);
1740 sig_req(plci,INFO_REQ,0);
1741 send_req(plci);
1742 return false;
1745 if(plci->State && ai_parms[2].length)
1747 /* User_Info option */
1748 dbug(1,dprintf("UUI"));
1749 add_s(plci,UUI,&ai_parms[2]);
1750 sig_req(plci,USER_DATA,0);
1752 else if(plci->State && ai_parms[3].length)
1754 /* Facility option */
1755 dbug(1,dprintf("FAC"));
1756 add_s(plci,CPN,&msg[0]);
1757 add_ai(plci, &msg[1]);
1758 sig_req(plci,FACILITY_REQ,0);
1760 else
1762 Info = _WRONG_STATE;
1765 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1767 /* NCR_Facility option -> send UUI and Keypad too */
1768 dbug(1,dprintf("NCR_FAC"));
1769 if((i=get_plci(a)))
1771 rc_plci = &a->plci[i-1];
1772 appl->NullCREnable = true;
1773 rc_plci->internal_command = C_NCR_FAC_REQ;
1774 rc_plci->appl = appl;
1775 add_p(rc_plci,CAI,"\x01\x80");
1776 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1777 sig_req(rc_plci,ASSIGN,DSIG_ID);
1778 send_req(rc_plci);
1780 else
1782 Info = _OUT_OF_PLCI;
1785 if(!Info)
1787 add_s(rc_plci,CPN,&msg[0]);
1788 add_ai(rc_plci, &msg[1]);
1789 sig_req(rc_plci,NCR_FACILITY,0);
1790 send_req(rc_plci);
1791 return false;
1792 /* for application controlled supplementary services */
1796 if (!rc_plci)
1798 Info = _WRONG_MESSAGE_FORMAT;
1801 if(!Info)
1803 send_req(rc_plci);
1805 else
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1,dprintf("localInfoCon"));
1808 sendf(appl,
1809 _INFO_R|CONFIRM,
1811 Number,
1812 "w",Info);
1814 return false;
1817 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1819 dbug(1,dprintf("info_res"));
1820 return false;
1823 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1825 word Info;
1826 byte ret;
1828 dbug(1,dprintf("alert_req"));
1830 Info = _WRONG_IDENTIFIER;
1831 ret = false;
1832 if(plci) {
1833 Info = _ALERT_IGNORED;
1834 if(plci->State!=INC_CON_ALERT) {
1835 Info = _WRONG_STATE;
1836 if(plci->State==INC_CON_PENDING) {
1837 Info = 0;
1838 plci->State=INC_CON_ALERT;
1839 add_ai(plci, &msg[0]);
1840 sig_req(plci,CALL_ALERT,0);
1841 ret = 1;
1845 sendf(appl,
1846 _ALERT_R|CONFIRM,
1848 Number,
1849 "w",Info);
1850 return ret;
1853 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1855 word Info = 0;
1856 word i = 0;
1858 word selector;
1859 word SSreq;
1860 long relatedPLCIvalue;
1861 DIVA_CAPI_ADAPTER * relatedadapter;
1862 byte * SSparms = "";
1863 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1864 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1865 API_PARSE * parms;
1866 API_PARSE ss_parms[11];
1867 PLCI *rplci;
1868 byte cai[15];
1869 dword d;
1870 API_PARSE dummy;
1872 dbug(1,dprintf("facility_req"));
1873 for(i=0;i<9;i++) ss_parms[i].length = 0;
1875 parms = &msg[1];
1877 if(!a)
1879 dbug(1,dprintf("wrong Ctrl"));
1880 Info = _WRONG_IDENTIFIER;
1883 selector = GET_WORD(msg[0].info);
1885 if(!Info)
1887 switch(selector)
1889 case SELECTOR_HANDSET:
1890 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1891 break;
1893 case SELECTOR_SU_SERV:
1894 if(!msg[1].length)
1896 Info = _WRONG_MESSAGE_FORMAT;
1897 break;
1899 SSreq = GET_WORD(&(msg[1].info[1]));
1900 PUT_WORD(&RCparms[1],SSreq);
1901 SSparms = RCparms;
1902 switch(SSreq)
1904 case S_GET_SUPPORTED_SERVICES:
1905 if((i=get_plci(a)))
1907 rplci = &a->plci[i-1];
1908 rplci->appl = appl;
1909 add_p(rplci,CAI,"\x01\x80");
1910 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1911 sig_req(rplci,ASSIGN,DSIG_ID);
1912 send_req(rplci);
1914 else
1916 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1917 SSparms = (byte *)SSstruct;
1918 break;
1920 rplci->internal_command = GETSERV_REQ_PEND;
1921 rplci->number = Number;
1922 rplci->appl = appl;
1923 sig_req(rplci,S_SUPPORTED,0);
1924 send_req(rplci);
1925 return false;
1926 break;
1928 case S_LISTEN:
1929 if(parms->length==7)
1931 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1933 dbug(1,dprintf("format wrong"));
1934 Info = _WRONG_MESSAGE_FORMAT;
1935 break;
1938 else
1940 Info = _WRONG_MESSAGE_FORMAT;
1941 break;
1943 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1944 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1946 if((i=get_plci(a)))
1948 rplci = &a->plci[i-1];
1949 rplci->appl = appl;
1950 add_p(rplci,CAI,"\x01\x80");
1951 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1952 sig_req(rplci,ASSIGN,DSIG_ID);
1953 send_req(rplci);
1955 else
1957 break;
1959 rplci->internal_command = GET_MWI_STATE;
1960 rplci->number = Number;
1961 sig_req(rplci,MWI_POLL,0);
1962 send_req(rplci);
1964 break;
1966 case S_HOLD:
1967 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1968 if(plci && plci->State && plci->SuppState==IDLE)
1970 plci->SuppState = HOLD_REQUEST;
1971 plci->command = C_HOLD_REQ;
1972 add_s(plci,CAI,&ss_parms[1]);
1973 sig_req(plci,CALL_HOLD,0);
1974 send_req(plci);
1975 return false;
1977 else Info = 0x3010; /* wrong state */
1978 break;
1979 case S_RETRIEVE:
1980 if(plci && plci->State && plci->SuppState==CALL_HELD)
1982 if(Id & EXT_CONTROLLER)
1984 if(AdvCodecSupport(a, plci, appl, 0))
1986 Info = 0x3010; /* wrong state */
1987 break;
1990 else plci->tel = 0;
1992 plci->SuppState = RETRIEVE_REQUEST;
1993 plci->command = C_RETRIEVE_REQ;
1994 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1996 plci->spoofed_msg = CALL_RETRIEVE;
1997 plci->internal_command = BLOCK_PLCI;
1998 plci->command = 0;
1999 dbug(1,dprintf("Spoof"));
2000 return false;
2002 else
2004 sig_req(plci,CALL_RETRIEVE,0);
2005 send_req(plci);
2006 return false;
2009 else Info = 0x3010; /* wrong state */
2010 break;
2011 case S_SUSPEND:
2012 if(parms->length)
2014 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2016 dbug(1,dprintf("format wrong"));
2017 Info = _WRONG_MESSAGE_FORMAT;
2018 break;
2021 if(plci && plci->State)
2023 add_s(plci,CAI,&ss_parms[2]);
2024 plci->command = SUSPEND_REQ;
2025 sig_req(plci,SUSPEND,0);
2026 plci->State = SUSPENDING;
2027 send_req(plci);
2029 else Info = 0x3010; /* wrong state */
2030 break;
2032 case S_RESUME:
2033 if(!(i=get_plci(a)) )
2035 Info = _OUT_OF_PLCI;
2036 break;
2038 rplci = &a->plci[i-1];
2039 rplci->appl = appl;
2040 rplci->number = Number;
2041 rplci->tel = 0;
2042 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2043 /* check 'external controller' bit for codec support */
2044 if(Id & EXT_CONTROLLER)
2046 if(AdvCodecSupport(a, rplci, appl, 0) )
2048 rplci->Id = 0;
2049 Info = 0x300A;
2050 break;
2053 if(parms->length)
2055 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2057 dbug(1,dprintf("format wrong"));
2058 rplci->Id = 0;
2059 Info = _WRONG_MESSAGE_FORMAT;
2060 break;
2063 dummy.length = 0;
2064 dummy.info = "\x00";
2065 add_b1(rplci, &dummy, 0, 0);
2066 if (a->Info_Mask[appl->Id-1] & 0x200)
2068 /* early B3 connect (CIP mask bit 9) no release after a disc */
2069 add_p(rplci,LLI,"\x01\x01");
2071 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2072 sig_req(rplci,ASSIGN,DSIG_ID);
2073 send_req(rplci);
2074 add_s(rplci,CAI,&ss_parms[2]);
2075 rplci->command = RESUME_REQ;
2076 sig_req(rplci,RESUME,0);
2077 rplci->State = RESUMING;
2078 send_req(rplci);
2079 break;
2081 case S_CONF_BEGIN: /* Request */
2082 case S_CONF_DROP:
2083 case S_CONF_ISOLATE:
2084 case S_CONF_REATTACH:
2085 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2087 dbug(1,dprintf("format wrong"));
2088 Info = _WRONG_MESSAGE_FORMAT;
2089 break;
2091 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2093 d = GET_DWORD(ss_parms[2].info);
2094 if(d>=0x80)
2096 dbug(1,dprintf("format wrong"));
2097 Info = _WRONG_MESSAGE_FORMAT;
2098 break;
2100 plci->ptyState = (byte)SSreq;
2101 plci->command = 0;
2102 cai[0] = 2;
2103 switch(SSreq)
2105 case S_CONF_BEGIN:
2106 cai[1] = CONF_BEGIN;
2107 plci->internal_command = CONF_BEGIN_REQ_PEND;
2108 break;
2109 case S_CONF_DROP:
2110 cai[1] = CONF_DROP;
2111 plci->internal_command = CONF_DROP_REQ_PEND;
2112 break;
2113 case S_CONF_ISOLATE:
2114 cai[1] = CONF_ISOLATE;
2115 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2116 break;
2117 case S_CONF_REATTACH:
2118 cai[1] = CONF_REATTACH;
2119 plci->internal_command = CONF_REATTACH_REQ_PEND;
2120 break;
2122 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2123 add_p(plci,CAI,cai);
2124 sig_req(plci,S_SERVICE,0);
2125 send_req(plci);
2126 return false;
2128 else Info = 0x3010; /* wrong state */
2129 break;
2131 case S_ECT:
2132 case S_3PTY_BEGIN:
2133 case S_3PTY_END:
2134 case S_CONF_ADD:
2135 if(parms->length==7)
2137 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2139 dbug(1,dprintf("format wrong"));
2140 Info = _WRONG_MESSAGE_FORMAT;
2141 break;
2144 else if(parms->length==8) /* workaround for the T-View-S */
2146 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2148 dbug(1,dprintf("format wrong"));
2149 Info = _WRONG_MESSAGE_FORMAT;
2150 break;
2153 else
2155 Info = _WRONG_MESSAGE_FORMAT;
2156 break;
2158 if(!msg[1].length)
2160 Info = _WRONG_MESSAGE_FORMAT;
2161 break;
2163 if (!plci)
2165 Info = _WRONG_IDENTIFIER;
2166 break;
2168 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2169 relatedPLCIvalue &= 0x0000FFFF;
2170 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2171 /* controller starts with 0 up to (max_adapter - 1) */
2172 if (((relatedPLCIvalue & 0x7f) == 0)
2173 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2174 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2176 if(SSreq==S_3PTY_END)
2178 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2179 rplci = plci;
2181 else
2183 Info = 0x3010; /* wrong state */
2184 break;
2187 else
2189 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2190 relatedPLCIvalue >>=8;
2191 /* find PLCI PTR*/
2192 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2194 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2196 rplci = &relatedadapter->plci[i];
2199 if(!rplci || !relatedPLCIvalue)
2201 if(SSreq==S_3PTY_END)
2203 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2204 rplci = plci;
2206 else
2208 Info = 0x3010; /* wrong state */
2209 break;
2214 dbug(1,dprintf("rplci:%x",rplci));
2215 dbug(1,dprintf("plci:%x",plci));
2216 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2217 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2218 dbug(1,dprintf("SSreq:%x",SSreq));
2219 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2220 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2221 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2223 /* send PTY/ECT req, cannot check all states because of US stuff */
2224 if( !rplci->internal_command && rplci->appl )
2226 plci->command = 0;
2227 rplci->relatedPTYPLCI = plci;
2228 plci->relatedPTYPLCI = rplci;
2229 rplci->ptyState = (byte)SSreq;
2230 if(SSreq==S_ECT)
2232 rplci->internal_command = ECT_REQ_PEND;
2233 cai[1] = ECT_EXECUTE;
2235 rplci->vswitchstate=0;
2236 rplci->vsprot=0;
2237 rplci->vsprotdialect=0;
2238 plci->vswitchstate=0;
2239 plci->vsprot=0;
2240 plci->vsprotdialect=0;
2243 else if(SSreq==S_CONF_ADD)
2245 rplci->internal_command = CONF_ADD_REQ_PEND;
2246 cai[1] = CONF_ADD;
2248 else
2250 rplci->internal_command = PTY_REQ_PEND;
2251 cai[1] = (byte)(SSreq-3);
2253 rplci->number = Number;
2254 if(plci!=rplci) /* explicit invocation */
2256 cai[0] = 2;
2257 cai[2] = plci->Sig.Id;
2258 dbug(1,dprintf("explicit invocation"));
2260 else
2262 dbug(1,dprintf("implicit invocation"));
2263 cai[0] = 1;
2265 add_p(rplci,CAI,cai);
2266 sig_req(rplci,S_SERVICE,0);
2267 send_req(rplci);
2268 return false;
2270 else
2272 dbug(0,dprintf("Wrong line"));
2273 Info = 0x3010; /* wrong state */
2274 break;
2276 break;
2278 case S_CALL_DEFLECTION:
2279 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2281 dbug(1,dprintf("format wrong"));
2282 Info = _WRONG_MESSAGE_FORMAT;
2283 break;
2285 if (!plci)
2287 Info = _WRONG_IDENTIFIER;
2288 break;
2290 /* reuse unused screening indicator */
2291 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2292 plci->command = 0;
2293 plci->internal_command = CD_REQ_PEND;
2294 appl->CDEnable = true;
2295 cai[0] = 1;
2296 cai[1] = CALL_DEFLECTION;
2297 add_p(plci,CAI,cai);
2298 add_p(plci,CPN,ss_parms[3].info);
2299 sig_req(plci,S_SERVICE,0);
2300 send_req(plci);
2301 return false;
2302 break;
2304 case S_CALL_FORWARDING_START:
2305 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2307 dbug(1,dprintf("format wrong"));
2308 Info = _WRONG_MESSAGE_FORMAT;
2309 break;
2312 if((i=get_plci(a)))
2314 rplci = &a->plci[i-1];
2315 rplci->appl = appl;
2316 add_p(rplci,CAI,"\x01\x80");
2317 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2318 sig_req(rplci,ASSIGN,DSIG_ID);
2319 send_req(rplci);
2321 else
2323 Info = _OUT_OF_PLCI;
2324 break;
2327 /* reuse unused screening indicator */
2328 rplci->internal_command = CF_START_PEND;
2329 rplci->appl = appl;
2330 rplci->number = Number;
2331 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2332 cai[0] = 2;
2333 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2334 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2335 add_p(rplci,CAI,cai);
2336 add_p(rplci,OAD,ss_parms[5].info);
2337 add_p(rplci,CPN,ss_parms[6].info);
2338 sig_req(rplci,S_SERVICE,0);
2339 send_req(rplci);
2340 return false;
2341 break;
2343 case S_INTERROGATE_DIVERSION:
2344 case S_INTERROGATE_NUMBERS:
2345 case S_CALL_FORWARDING_STOP:
2346 case S_CCBS_REQUEST:
2347 case S_CCBS_DEACTIVATE:
2348 case S_CCBS_INTERROGATE:
2349 switch(SSreq)
2351 case S_INTERROGATE_NUMBERS:
2352 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2354 dbug(0,dprintf("format wrong"));
2355 Info = _WRONG_MESSAGE_FORMAT;
2357 break;
2358 case S_CCBS_REQUEST:
2359 case S_CCBS_DEACTIVATE:
2360 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2362 dbug(0,dprintf("format wrong"));
2363 Info = _WRONG_MESSAGE_FORMAT;
2365 break;
2366 case S_CCBS_INTERROGATE:
2367 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2369 dbug(0,dprintf("format wrong"));
2370 Info = _WRONG_MESSAGE_FORMAT;
2372 break;
2373 default:
2374 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2376 dbug(0,dprintf("format wrong"));
2377 Info = _WRONG_MESSAGE_FORMAT;
2378 break;
2380 break;
2383 if(Info) break;
2384 if((i=get_plci(a)))
2386 rplci = &a->plci[i-1];
2387 switch(SSreq)
2389 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2390 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2391 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2392 break;
2393 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2394 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2395 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2396 break;
2397 case S_CALL_FORWARDING_STOP:
2398 rplci->internal_command = CF_STOP_PEND;
2399 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400 break;
2401 case S_CCBS_REQUEST:
2402 cai[1] = CCBS_REQUEST;
2403 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2404 break;
2405 case S_CCBS_DEACTIVATE:
2406 cai[1] = CCBS_DEACTIVATE;
2407 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2408 break;
2409 case S_CCBS_INTERROGATE:
2410 cai[1] = CCBS_INTERROGATE;
2411 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2412 break;
2413 default:
2414 cai[1] = 0;
2415 break;
2417 rplci->appl = appl;
2418 rplci->number = Number;
2419 add_p(rplci,CAI,"\x01\x80");
2420 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2421 sig_req(rplci,ASSIGN,DSIG_ID);
2422 send_req(rplci);
2424 else
2426 Info = _OUT_OF_PLCI;
2427 break;
2430 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2431 switch(SSreq)
2433 case S_INTERROGATE_NUMBERS:
2434 cai[0] = 1;
2435 add_p(rplci,CAI,cai);
2436 break;
2437 case S_CCBS_REQUEST:
2438 case S_CCBS_DEACTIVATE:
2439 cai[0] = 3;
2440 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2441 add_p(rplci,CAI,cai);
2442 break;
2443 case S_CCBS_INTERROGATE:
2444 cai[0] = 3;
2445 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2446 add_p(rplci,CAI,cai);
2447 add_p(rplci,OAD,ss_parms[4].info);
2448 break;
2449 default:
2450 cai[0] = 2;
2451 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2452 add_p(rplci,CAI,cai);
2453 add_p(rplci,OAD,ss_parms[5].info);
2454 break;
2457 sig_req(rplci,S_SERVICE,0);
2458 send_req(rplci);
2459 return false;
2460 break;
2462 case S_MWI_ACTIVATE:
2463 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2465 dbug(1,dprintf("format wrong"));
2466 Info = _WRONG_MESSAGE_FORMAT;
2467 break;
2469 if(!plci)
2471 if((i=get_plci(a)))
2473 rplci = &a->plci[i-1];
2474 rplci->appl = appl;
2475 rplci->cr_enquiry=true;
2476 add_p(rplci,CAI,"\x01\x80");
2477 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2478 sig_req(rplci,ASSIGN,DSIG_ID);
2479 send_req(rplci);
2481 else
2483 Info = _OUT_OF_PLCI;
2484 break;
2487 else
2489 rplci = plci;
2490 rplci->cr_enquiry=false;
2493 rplci->command = 0;
2494 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2495 rplci->appl = appl;
2496 rplci->number = Number;
2498 cai[0] = 13;
2499 cai[1] = ACTIVATION_MWI; /* Function */
2500 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2501 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2502 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2503 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2504 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2505 add_p(rplci,CAI,cai);
2506 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2507 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2508 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2509 add_p(rplci,UID,ss_parms[10].info); /* Time */
2510 sig_req(rplci,S_SERVICE,0);
2511 send_req(rplci);
2512 return false;
2514 case S_MWI_DEACTIVATE:
2515 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2517 dbug(1,dprintf("format wrong"));
2518 Info = _WRONG_MESSAGE_FORMAT;
2519 break;
2521 if(!plci)
2523 if((i=get_plci(a)))
2525 rplci = &a->plci[i-1];
2526 rplci->appl = appl;
2527 rplci->cr_enquiry=true;
2528 add_p(rplci,CAI,"\x01\x80");
2529 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2530 sig_req(rplci,ASSIGN,DSIG_ID);
2531 send_req(rplci);
2533 else
2535 Info = _OUT_OF_PLCI;
2536 break;
2539 else
2541 rplci = plci;
2542 rplci->cr_enquiry=false;
2545 rplci->command = 0;
2546 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2547 rplci->appl = appl;
2548 rplci->number = Number;
2550 cai[0] = 5;
2551 cai[1] = DEACTIVATION_MWI; /* Function */
2552 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2553 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2554 add_p(rplci,CAI,cai);
2555 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2556 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2557 sig_req(rplci,S_SERVICE,0);
2558 send_req(rplci);
2559 return false;
2561 default:
2562 Info = 0x300E; /* not supported */
2563 break;
2565 break; /* case SELECTOR_SU_SERV: end */
2568 case SELECTOR_DTMF:
2569 return (dtmf_request (Id, Number, a, plci, appl, msg));
2573 case SELECTOR_LINE_INTERCONNECT:
2574 return (mixer_request (Id, Number, a, plci, appl, msg));
2578 case PRIV_SELECTOR_ECHO_CANCELLER:
2579 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2580 return (ec_request (Id, Number, a, plci, appl, msg));
2582 case SELECTOR_ECHO_CANCELLER:
2583 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2584 return (ec_request (Id, Number, a, plci, appl, msg));
2587 case SELECTOR_V42BIS:
2588 default:
2589 Info = _FACILITY_NOT_SUPPORTED;
2590 break;
2591 } /* end of switch(selector) */
2594 dbug(1,dprintf("SendFacRc"));
2595 sendf(appl,
2596 _FACILITY_R|CONFIRM,
2598 Number,
2599 "wws",Info,selector,SSparms);
2600 return false;
2603 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
2605 dbug(1,dprintf("facility_res"));
2606 return false;
2609 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2611 word Info = 0;
2612 byte req;
2613 byte len;
2614 word w;
2615 word fax_control_bits, fax_feature_bits, fax_info_change;
2616 API_PARSE * ncpi;
2617 byte pvc[2];
2619 API_PARSE fax_parms[9];
2620 word i;
2623 dbug(1,dprintf("connect_b3_req"));
2624 if(plci)
2626 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2627 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2629 Info = _WRONG_STATE;
2631 else
2633 /* local reply if assign unsuccessfull
2634 or B3 protocol allows only one layer 3 connection
2635 and already connected
2636 or B2 protocol not any LAPD
2637 and connect_b3_req contradicts originate/answer direction */
2638 if (!plci->NL.Id
2639 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2640 && ((plci->channels != 0)
2641 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2642 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2644 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2645 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2646 Info = _WRONG_STATE;
2647 sendf(appl,
2648 _CONNECT_B3_R|CONFIRM,
2650 Number,
2651 "w",Info);
2652 return false;
2654 plci->requested_options_conn = 0;
2656 req = N_CONNECT;
2657 ncpi = &parms[0];
2658 if(plci->B3_prot==2 || plci->B3_prot==3)
2660 if(ncpi->length>2)
2662 /* check for PVC */
2663 if(ncpi->info[2] || ncpi->info[3])
2665 pvc[0] = ncpi->info[3];
2666 pvc[1] = ncpi->info[2];
2667 add_d(plci,2,pvc);
2668 req = N_RESET;
2670 else
2672 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2673 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2677 else if(plci->B3_prot==5)
2679 if (plci->NL.Id && !plci->nl_remove_id)
2681 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2682 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2683 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2684 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2686 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2687 fax_info_change = false;
2688 if (ncpi->length >= 4)
2690 w = GET_WORD(&ncpi->info[3]);
2691 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2693 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2694 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2695 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2696 fax_info_change = true;
2698 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2699 if (w & 0x0002) /* Fax-polling request */
2700 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2701 if ((w & 0x0004) /* Request to send / poll another document */
2702 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2704 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2706 if (ncpi->length >= 6)
2708 w = GET_WORD(&ncpi->info[5]);
2709 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2711 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2712 fax_info_change = true;
2715 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2716 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2718 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2720 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2721 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2723 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2725 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2726 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2727 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2728 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2730 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2731 Info = _WRONG_MESSAGE_FORMAT;
2732 else
2734 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2735 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2737 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2738 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2739 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2741 w = fax_parms[4].length;
2742 if (w > 20)
2743 w = 20;
2744 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2745 for (i = 0; i < w; i++)
2746 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2747 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2748 len = (byte)(((T30_INFO *) 0)->station_id + 20);
2749 w = fax_parms[5].length;
2750 if (w > 20)
2751 w = 20;
2752 plci->fax_connect_info_buffer[len++] = (byte) w;
2753 for (i = 0; i < w; i++)
2754 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2755 w = fax_parms[6].length;
2756 if (w > 20)
2757 w = 20;
2758 plci->fax_connect_info_buffer[len++] = (byte) w;
2759 for (i = 0; i < w; i++)
2760 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2761 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2762 & (1L << PRIVATE_FAX_NONSTANDARD))
2764 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2766 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2767 plci->fax_connect_info_buffer[len++] = 0;
2769 else
2771 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2772 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2773 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2774 for (i = 0; i < fax_parms[7].length; i++)
2775 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2780 else
2782 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2784 fax_info_change = true;
2787 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2789 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2790 fax_info_change = true;
2793 if (Info == GOOD)
2795 plci->fax_connect_info_length = len;
2796 if (fax_info_change)
2798 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2800 start_internal_command (Id, plci, fax_connect_info_command);
2801 return false;
2803 else
2805 start_internal_command (Id, plci, fax_adjust_b23_command);
2806 return false;
2811 else Info = _WRONG_STATE;
2813 else Info = _WRONG_STATE;
2816 else if (plci->B3_prot == B3_RTP)
2818 plci->internal_req_buffer[0] = ncpi->length + 1;
2819 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2820 for (w = 0; w < ncpi->length; w++)
2821 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2822 start_internal_command (Id, plci, rtp_connect_b3_req_command);
2823 return false;
2826 if(!Info)
2828 nl_req_ncci(plci,req,0);
2829 return 1;
2833 else Info = _WRONG_IDENTIFIER;
2835 sendf(appl,
2836 _CONNECT_B3_R|CONFIRM,
2838 Number,
2839 "w",Info);
2840 return false;
2843 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2845 word ncci;
2846 API_PARSE * ncpi;
2847 byte req;
2849 word w;
2852 API_PARSE fax_parms[9];
2853 word i;
2854 byte len;
2857 dbug(1,dprintf("connect_b3_res"));
2859 ncci = (word)(Id>>16);
2860 if(plci && ncci) {
2861 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2862 if (GET_WORD (&parms[0].info[0]) != 0)
2864 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2865 channel_request_xon (plci, a->ncci_ch[ncci]);
2866 channel_xmit_xon (plci);
2867 cleanup_ncci_data (plci, ncci);
2868 nl_req_ncci(plci,N_DISC,(byte)ncci);
2869 return 1;
2871 a->ncci_state[ncci] = INC_ACT_PENDING;
2873 req = N_CONNECT_ACK;
2874 ncpi = &parms[1];
2875 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2878 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2879 & (1L << PRIVATE_FAX_NONSTANDARD))
2881 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2882 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2883 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2885 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2886 if (plci->fax_connect_info_length < len)
2888 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2889 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2891 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2893 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2895 else
2897 if (plci->fax_connect_info_length <= len)
2898 plci->fax_connect_info_buffer[len] = 0;
2899 len += 1 + plci->fax_connect_info_buffer[len];
2900 if (plci->fax_connect_info_length <= len)
2901 plci->fax_connect_info_buffer[len] = 0;
2902 len += 1 + plci->fax_connect_info_buffer[len];
2903 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2904 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2905 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2906 for (i = 0; i < fax_parms[7].length; i++)
2907 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2909 plci->fax_connect_info_length = len;
2910 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2911 start_internal_command (Id, plci, fax_connect_ack_command);
2912 return false;
2916 nl_req_ncci(plci,req,(byte)ncci);
2917 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2918 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2920 if (plci->B3_prot == 4)
2921 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2922 else
2923 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2924 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2928 else if (plci->B3_prot == B3_RTP)
2930 plci->internal_req_buffer[0] = ncpi->length + 1;
2931 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2932 for (w = 0; w < ncpi->length; w++)
2933 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2934 start_internal_command (Id, plci, rtp_connect_b3_res_command);
2935 return false;
2938 else
2940 if(ncpi->length>2) {
2941 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2942 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2944 nl_req_ncci(plci,req,(byte)ncci);
2945 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2946 if (plci->adjust_b_restore)
2948 plci->adjust_b_restore = false;
2949 start_internal_command (Id, plci, adjust_b_restore);
2952 return 1;
2955 return false;
2958 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2960 word ncci;
2962 ncci = (word)(Id>>16);
2963 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2965 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2966 && (plci->State != OUTG_DIS_PENDING))
2968 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2969 a->ncci_state[ncci] = CONNECTED;
2970 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2971 channel_request_xon (plci, a->ncci_ch[ncci]);
2972 channel_xmit_xon (plci);
2975 return false;
2978 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2980 word Info;
2981 word ncci;
2982 API_PARSE * ncpi;
2984 dbug(1,dprintf("disconnect_b3_req"));
2986 Info = _WRONG_IDENTIFIER;
2987 ncci = (word)(Id>>16);
2988 if (plci && ncci)
2990 Info = _WRONG_STATE;
2991 if ((a->ncci_state[ncci] == CONNECTED)
2992 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2993 || (a->ncci_state[ncci] == INC_CON_PENDING)
2994 || (a->ncci_state[ncci] == INC_ACT_PENDING))
2996 a->ncci_state[ncci] = OUTG_DIS_PENDING;
2997 channel_request_xon (plci, a->ncci_ch[ncci]);
2998 channel_xmit_xon (plci);
3000 if (a->ncci[ncci].data_pending
3001 && ((plci->B3_prot == B3_TRANSPARENT)
3002 || (plci->B3_prot == B3_T30)
3003 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3005 plci->send_disc = (byte)ncci;
3006 plci->command = 0;
3007 return false;
3009 else
3011 cleanup_ncci_data (plci, ncci);
3013 if(plci->B3_prot==2 || plci->B3_prot==3)
3015 ncpi = &parms[0];
3016 if(ncpi->length>3)
3018 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3021 nl_req_ncci(plci,N_DISC,(byte)ncci);
3023 return 1;
3026 sendf(appl,
3027 _DISCONNECT_B3_R|CONFIRM,
3029 Number,
3030 "w",Info);
3031 return false;
3034 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3036 word ncci;
3037 word i;
3039 ncci = (word)(Id>>16);
3040 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3041 if(plci && ncci) {
3042 plci->requested_options_conn = 0;
3043 plci->fax_connect_info_length = 0;
3044 plci->ncpi_state = 0x00;
3045 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3046 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3048 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3050 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3051 if(i<MAX_CHANNELS_PER_PLCI) {
3052 if(plci->channels)plci->channels--;
3053 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3054 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3056 ncci_free_receive_buffers (plci, ncci);
3058 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3059 if(plci->State == SUSPENDING){
3060 sendf(plci->appl,
3061 _FACILITY_I,
3062 Id & 0xffffL,
3064 "ws", (word)3, "\x03\x04\x00\x00");
3065 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3067 plci_remove(plci);
3068 plci->State=IDLE;
3071 else
3073 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3074 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3075 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3077 ncci_free_receive_buffers (plci, ncci);
3079 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3081 plci->adapter->ncci_state[ncci] = IDLE;
3082 start_internal_command (Id, plci, fax_disconnect_command);
3083 return 1;
3087 return false;
3090 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3092 NCCI *ncci_ptr;
3093 DATA_B3_DESC *data;
3094 word Info;
3095 word ncci;
3096 word i;
3098 dbug(1,dprintf("data_b3_req"));
3100 Info = _WRONG_IDENTIFIER;
3101 ncci = (word)(Id>>16);
3102 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3104 if (plci && ncci)
3106 Info = _WRONG_STATE;
3107 if ((a->ncci_state[ncci] == CONNECTED)
3108 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3110 /* queue data */
3111 ncci_ptr = &(a->ncci[ncci]);
3112 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3113 if (i >= MAX_DATA_B3)
3114 i -= MAX_DATA_B3;
3115 data = &(ncci_ptr->DBuffer[i]);
3116 data->Number = Number;
3117 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3118 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3121 data->P = (byte *)(*((dword *)(parms[0].info)));
3124 else
3125 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3126 data->Length = GET_WORD(parms[1].info);
3127 data->Handle = GET_WORD(parms[2].info);
3128 data->Flags = GET_WORD(parms[3].info);
3129 (ncci_ptr->data_pending)++;
3131 /* check for delivery confirmation */
3132 if (data->Flags & 0x0004)
3134 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3135 if (i >= MAX_DATA_ACK)
3136 i -= MAX_DATA_ACK;
3137 ncci_ptr->DataAck[i].Number = data->Number;
3138 ncci_ptr->DataAck[i].Handle = data->Handle;
3139 (ncci_ptr->data_ack_pending)++;
3142 send_data(plci);
3143 return false;
3146 if (appl)
3148 if (plci)
3150 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3151 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3154 TransmitBufferFree (appl, (byte *)(*((dword *)(parms[0].info))));
3158 sendf(appl,
3159 _DATA_B3_R|CONFIRM,
3161 Number,
3162 "ww",GET_WORD(parms[2].info),Info);
3164 return false;
3167 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3169 word n;
3170 word ncci;
3171 word NCCIcode;
3173 dbug(1,dprintf("data_b3_res"));
3175 ncci = (word)(Id>>16);
3176 if(plci && ncci) {
3177 n = GET_WORD(parms[0].info);
3178 dbug(1,dprintf("free(%d)",n));
3179 NCCIcode = ncci | (((word) a->Id) << 8);
3180 if(n<appl->MaxBuffer &&
3181 appl->DataNCCI[n]==NCCIcode &&
3182 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3183 dbug(1,dprintf("found"));
3184 appl->DataNCCI[n] = 0;
3186 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3187 channel_request_xon (plci, a->ncci_ch[ncci]);
3189 channel_xmit_xon (plci);
3191 if(appl->DataFlags[n] &4) {
3192 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3193 return 1;
3197 return false;
3200 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3202 word Info;
3203 word ncci;
3205 dbug(1,dprintf("reset_b3_req"));
3207 Info = _WRONG_IDENTIFIER;
3208 ncci = (word)(Id>>16);
3209 if(plci && ncci)
3211 Info = _WRONG_STATE;
3212 switch (plci->B3_prot)
3214 case B3_ISO8208:
3215 case B3_X25_DCE:
3216 if(a->ncci_state[ncci]==CONNECTED)
3218 nl_req_ncci(plci,N_RESET,(byte)ncci);
3219 send_req(plci);
3220 Info = GOOD;
3222 break;
3223 case B3_TRANSPARENT:
3224 if(a->ncci_state[ncci]==CONNECTED)
3226 start_internal_command (Id, plci, reset_b3_command);
3227 Info = GOOD;
3229 break;
3232 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3233 sendf(appl,
3234 _RESET_B3_R|CONFIRM,
3236 Number,
3237 "w",Info);
3238 return false;
3241 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3243 word ncci;
3245 dbug(1,dprintf("reset_b3_res"));
3247 ncci = (word)(Id>>16);
3248 if(plci && ncci) {
3249 switch (plci->B3_prot)
3251 case B3_ISO8208:
3252 case B3_X25_DCE:
3253 if(a->ncci_state[ncci]==INC_RES_PENDING)
3255 a->ncci_state[ncci] = CONNECTED;
3256 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3257 return true;
3259 break;
3262 return false;
3265 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3267 word ncci;
3268 API_PARSE * ncpi;
3269 byte req;
3271 dbug(1,dprintf("connect_b3_t90_a_res"));
3273 ncci = (word)(Id>>16);
3274 if(plci && ncci) {
3275 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3276 a->ncci_state[ncci] = CONNECTED;
3278 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3279 a->ncci_state[ncci] = CONNECTED;
3281 req = N_CONNECT_ACK;
3283 /* parms[0]==0 for CAPI original message definition! */
3284 if(parms[0].info) {
3285 ncpi = &parms[1];
3286 if(ncpi->length>2) {
3287 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3288 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3291 nl_req_ncci(plci,req,(byte)ncci);
3292 return 1;
3295 return false;
3299 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3301 word Info=0;
3302 word i;
3303 byte tel;
3304 API_PARSE bp_parms[7];
3306 if(!plci || !msg)
3308 Info = _WRONG_IDENTIFIER;
3310 else
3312 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3313 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3314 dbug(1,dprintf("PlciState=0x%x",plci->State));
3315 for(i=0;i<7;i++) bp_parms[i].length = 0;
3317 /* check if no channel is open, no B3 connected only */
3318 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3319 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3321 Info = _WRONG_STATE;
3323 /* check message format and fill bp_parms pointer */
3324 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3326 Info = _WRONG_MESSAGE_FORMAT;
3328 else
3330 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3331 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3332 if(Id & EXT_CONTROLLER)
3334 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3335 return 0;
3337 plci->State=INC_CON_CONNECTED_ALERT;
3338 plci->appl = appl;
3339 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3340 dump_c_ind_mask (plci);
3341 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3342 { /* its quasi a connect */
3343 if(test_c_ind_mask_bit (plci, i))
3344 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3348 api_save_msg(msg, "s", &plci->saved_msg);
3349 tel = plci->tel;
3350 if(Id & EXT_CONTROLLER)
3352 if(tel) /* external controller in use by this PLCI */
3354 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3356 dbug(1,dprintf("Ext_Ctrl in use 1"));
3357 Info = _WRONG_STATE;
3360 else /* external controller NOT in use by this PLCI ? */
3362 if(a->AdvSignalPLCI)
3364 dbug(1,dprintf("Ext_Ctrl in use 2"));
3365 Info = _WRONG_STATE;
3367 else /* activate the codec */
3369 dbug(1,dprintf("Ext_Ctrl start"));
3370 if(AdvCodecSupport(a, plci, appl, 0) )
3372 dbug(1,dprintf("Error in codec procedures"));
3373 Info = _WRONG_STATE;
3375 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3377 plci->spoofed_msg = AWAITING_SELECT_B;
3378 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3379 plci->command = 0;
3380 dbug(1,dprintf("continue if codec loaded"));
3381 return false;
3386 else /* external controller bit is OFF */
3388 if(tel) /* external controller in use, need to switch off */
3390 if(a->AdvSignalAppl==appl)
3392 CodecIdCheck(a, plci);
3393 plci->tel = 0;
3394 plci->adv_nl = 0;
3395 dbug(1,dprintf("Ext_Ctrl disable"));
3397 else
3399 dbug(1,dprintf("Ext_Ctrl not requested"));
3403 if (!Info)
3405 if (plci->call_dir & CALL_DIR_OUT)
3406 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3407 else if (plci->call_dir & CALL_DIR_IN)
3408 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3409 start_internal_command (Id, plci, select_b_command);
3410 return false;
3414 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3415 return false;
3418 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3420 word command;
3421 word i;
3422 word ncci;
3423 API_PARSE * m;
3424 API_PARSE m_parms[5];
3425 word codec;
3426 byte req;
3427 byte ch;
3428 byte dir;
3429 static byte chi[2] = {0x01,0x00};
3430 static byte lli[2] = {0x01,0x00};
3431 static byte codec_cai[2] = {0x01,0x01};
3432 static byte null_msg = {0};
3433 static API_PARSE null_parms = { 0, &null_msg };
3434 PLCI * v_plci;
3435 word Info=0;
3437 dbug(1,dprintf("manufacturer_req"));
3438 for(i=0;i<5;i++) m_parms[i].length = 0;
3440 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441 Info = _WRONG_MESSAGE_FORMAT;
3443 command = GET_WORD(parms[1].info);
3444 m = &parms[2];
3445 if (!Info)
3447 switch(command) {
3448 case _DI_ASSIGN_PLCI:
3449 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450 Info = _WRONG_MESSAGE_FORMAT;
3451 break;
3453 codec = GET_WORD(m_parms[0].info);
3454 ch = m_parms[1].info[0];
3455 dir = m_parms[2].info[0];
3456 if((i=get_plci(a))) {
3457 plci = &a->plci[i-1];
3458 plci->appl = appl;
3459 plci->command = _MANUFACTURER_R;
3460 plci->m_command = command;
3461 plci->number = Number;
3462 plci->State = LOCAL_CONNECT;
3463 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3466 if((ch==1 || ch==2) && (dir<=2)) {
3467 chi[1] = (byte)(0x80|ch);
3468 lli[1] = 0;
3469 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470 switch(codec)
3472 case 0:
3473 Info = add_b1(plci,&m_parms[3],0,0);
3474 break;
3475 case 1:
3476 add_p(plci,CAI,codec_cai);
3477 break;
3478 /* manual 'swich on' to the codec support without signalling */
3479 /* first 'assign plci' with this function, then use */
3480 case 2:
3481 if(AdvCodecSupport(a, plci, appl, 0) ) {
3482 Info = _RESOURCE_ERROR;
3484 else {
3485 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486 lli[1] = 0x10; /* local call codec stream */
3488 break;
3491 plci->State = LOCAL_CONNECT;
3492 plci->manufacturer = true;
3493 plci->command = _MANUFACTURER_R;
3494 plci->m_command = command;
3495 plci->number = Number;
3497 if(!Info)
3499 add_p(plci,LLI,lli);
3500 add_p(plci,CHI,chi);
3501 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502 sig_req(plci,ASSIGN,DSIG_ID);
3504 if(!codec)
3506 Info = add_b23(plci,&m_parms[3]);
3507 if(!Info)
3509 nl_req_ncci(plci,ASSIGN,0);
3510 send_req(plci);
3513 if(!Info)
3515 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3518 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519 plci->spoofed_msg = AWAITING_MANUF_CON;
3520 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521 plci->command = 0;
3522 send_req(plci);
3523 return false;
3525 if(dir==1) {
3526 sig_req(plci,CALL_REQ,0);
3528 else if(!dir){
3529 sig_req(plci,LISTEN_REQ,0);
3531 send_req(plci);
3533 else
3535 sendf(appl,
3536 _MANUFACTURER_R|CONFIRM,
3538 Number,
3539 "dww",_DI_MANU_ID,command,Info);
3540 return 2;
3545 else Info = _OUT_OF_PLCI;
3546 break;
3548 case _DI_IDI_CTRL:
3549 if(!plci)
3551 Info = _WRONG_IDENTIFIER;
3552 break;
3554 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555 Info = _WRONG_MESSAGE_FORMAT;
3556 break;
3558 req = m_parms[0].info[0];
3559 plci->command = _MANUFACTURER_R;
3560 plci->m_command = command;
3561 plci->number = Number;
3562 if(req==CALL_REQ)
3564 plci->b_channel = getChannel(&m_parms[1]);
3565 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3568 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570 plci->command = 0;
3571 break;
3574 else if(req==LAW_REQ)
3576 plci->cr_enquiry = true;
3578 add_ss(plci,FTY,&m_parms[1]);
3579 sig_req(plci,req,0);
3580 send_req(plci);
3581 if(req==HANGUP)
3583 if (plci->NL.Id && !plci->nl_remove_id)
3585 if (plci->channels)
3587 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3589 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3591 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592 cleanup_ncci_data (plci, ncci);
3593 nl_req_ncci(plci,N_DISC,(byte)ncci);
3597 mixer_remove (plci);
3598 nl_req_ncci(plci,REMOVE,0);
3599 send_req(plci);
3602 break;
3604 case _DI_SIG_CTRL:
3605 /* signalling control for loop activation B-channel */
3606 if(!plci)
3608 Info = _WRONG_IDENTIFIER;
3609 break;
3611 if(m->length){
3612 plci->command = _MANUFACTURER_R;
3613 plci->number = Number;
3614 add_ss(plci,FTY,m);
3615 sig_req(plci,SIG_CTRL,0);
3616 send_req(plci);
3618 else Info = _WRONG_MESSAGE_FORMAT;
3619 break;
3621 case _DI_RXT_CTRL:
3622 /* activation control for receiver/transmitter B-channel */
3623 if(!plci)
3625 Info = _WRONG_IDENTIFIER;
3626 break;
3628 if(m->length){
3629 plci->command = _MANUFACTURER_R;
3630 plci->number = Number;
3631 add_ss(plci,FTY,m);
3632 sig_req(plci,DSP_CTRL,0);
3633 send_req(plci);
3635 else Info = _WRONG_MESSAGE_FORMAT;
3636 break;
3638 case _DI_ADV_CODEC:
3639 case _DI_DSP_CTRL:
3640 /* TEL_CTRL commands to support non standard adjustments: */
3641 /* Ring on/off, Handset micro volume, external micro vol. */
3642 /* handset+external speaker volume, receiver+transm. gain,*/
3643 /* handsfree on (hookinfo off), set mixer command */
3645 if(command == _DI_ADV_CODEC)
3647 if(!a->AdvCodecPLCI) {
3648 Info = _WRONG_STATE;
3649 break;
3651 v_plci = a->AdvCodecPLCI;
3653 else
3655 if (plci
3656 && (m->length >= 3)
3657 && (m->info[1] == 0x1c)
3658 && (m->info[2] >= 1))
3660 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3662 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3664 Info = _WRONG_STATE;
3665 break;
3667 a->adv_voice_coef_length = m->info[2] - 1;
3668 if (a->adv_voice_coef_length > m->length - 3)
3669 a->adv_voice_coef_length = (byte)(m->length - 3);
3670 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672 for (i = 0; i < a->adv_voice_coef_length; i++)
3673 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674 if (plci->B1_facilities & B1_FACILITY_VOICE)
3675 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676 break;
3678 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3680 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3682 Info = _FACILITY_NOT_SUPPORTED;
3683 break;
3686 plci->dtmf_parameter_length = m->info[2] - 1;
3687 if (plci->dtmf_parameter_length > m->length - 3)
3688 plci->dtmf_parameter_length = (byte)(m->length - 3);
3689 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691 for (i = 0; i < plci->dtmf_parameter_length; i++)
3692 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694 dtmf_parameter_write (plci);
3695 break;
3699 v_plci = plci;
3702 if(!v_plci)
3704 Info = _WRONG_IDENTIFIER;
3705 break;
3707 if(m->length){
3708 add_ss(v_plci,FTY,m);
3709 sig_req(v_plci,TEL_CTRL,0);
3710 send_req(v_plci);
3712 else Info = _WRONG_MESSAGE_FORMAT;
3714 break;
3716 case _DI_OPTIONS_REQUEST:
3717 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718 Info = _WRONG_MESSAGE_FORMAT;
3719 break;
3721 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3723 Info = _FACILITY_NOT_SUPPORTED;
3724 break;
3726 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727 break;
3731 default:
3732 Info = _WRONG_MESSAGE_FORMAT;
3733 break;
3737 sendf(appl,
3738 _MANUFACTURER_R|CONFIRM,
3740 Number,
3741 "dww",_DI_MANU_ID,command,Info);
3742 return false;
3746 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3748 word indication;
3750 API_PARSE m_parms[3];
3751 API_PARSE *ncpi;
3752 API_PARSE fax_parms[9];
3753 word i;
3754 byte len;
3757 dbug(1,dprintf("manufacturer_res"));
3759 if ((msg[0].length == 0)
3760 || (msg[1].length == 0)
3761 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3763 return false;
3765 indication = GET_WORD(msg[1].info);
3766 switch (indication)
3769 case _DI_NEGOTIATE_B3:
3770 if(!plci)
3771 break;
3772 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3773 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3775 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3776 break;
3778 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3780 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3781 break;
3783 ncpi = &m_parms[1];
3784 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3785 if (plci->fax_connect_info_length < len)
3787 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3788 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3790 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3792 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3794 else
3796 if (plci->fax_connect_info_length <= len)
3797 plci->fax_connect_info_buffer[len] = 0;
3798 len += 1 + plci->fax_connect_info_buffer[len];
3799 if (plci->fax_connect_info_length <= len)
3800 plci->fax_connect_info_buffer[len] = 0;
3801 len += 1 + plci->fax_connect_info_buffer[len];
3802 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3803 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3804 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3805 for (i = 0; i < fax_parms[7].length; i++)
3806 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3808 plci->fax_connect_info_length = len;
3809 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3810 start_internal_command (Id, plci, fax_edata_ack_command);
3811 break;
3814 return false;
3817 /*------------------------------------------------------------------*/
3818 /* IDI callback function */
3819 /*------------------------------------------------------------------*/
3821 void callback(ENTITY * e)
3823 DIVA_CAPI_ADAPTER * a;
3824 APPL * appl;
3825 PLCI * plci;
3826 CAPI_MSG *m;
3827 word i, j;
3828 byte rc;
3829 byte ch;
3830 byte req;
3831 byte global_req;
3832 int no_cancel_rc;
3834 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3835 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3837 a = &(adapter[(byte)e->user[0]]);
3838 plci = &(a->plci[e->user[1]]);
3839 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3842 If new protocol code and new XDI is used then CAPI should work
3843 fully in accordance with IDI cpec an look on callback field instead
3844 of Rc field for return codes.
3846 if (((e->complete == 0xff) && no_cancel_rc) ||
3847 (e->Rc && !no_cancel_rc)) {
3848 rc = e->Rc;
3849 ch = e->RcCh;
3850 req = e->Req;
3851 e->Rc = 0;
3853 if (e->user[0] & 0x8000)
3856 If REMOVE request was sent then we have to wait until
3857 return code with Id set to zero arrives.
3858 All other return codes should be ignored.
3860 if (req == REMOVE)
3862 if (e->Id)
3864 dbug(1,dprintf("cancel RC in REMOVE state"));
3865 return;
3867 channel_flow_control_remove (plci);
3868 for (i = 0; i < 256; i++)
3870 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3871 a->FlowControlIdTable[i] = 0;
3873 plci->nl_remove_id = 0;
3874 if (plci->rx_dma_descriptor > 0) {
3875 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3876 plci->rx_dma_descriptor = 0;
3879 if (rc == OK_FC)
3881 a->FlowControlIdTable[ch] = e->Id;
3882 a->FlowControlSkipTable[ch] = 0;
3884 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3885 a->ch_flow_plci[ch] = plci->Id;
3886 plci->nl_req = 0;
3888 else
3891 Cancel return codes self, if feature was requested
3893 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3894 a->FlowControlIdTable[ch] = 0;
3895 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3896 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3897 return;
3901 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3903 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3904 if (ch == e->ReqCh)
3905 plci->nl_req = 0;
3907 else
3908 plci->nl_req = 0;
3910 if (plci->nl_req)
3911 control_rc (plci, 0, rc, ch, 0, true);
3912 else
3914 if (req == N_XON)
3916 channel_x_on (plci, ch);
3917 if (plci->internal_command)
3918 control_rc (plci, req, rc, ch, 0, true);
3920 else
3922 if (plci->nl_global_req)
3924 global_req = plci->nl_global_req;
3925 plci->nl_global_req = 0;
3926 if (rc != ASSIGN_OK) {
3927 e->Id = 0;
3928 if (plci->rx_dma_descriptor > 0) {
3929 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3930 plci->rx_dma_descriptor = 0;
3933 channel_xmit_xon (plci);
3934 control_rc (plci, 0, rc, ch, global_req, true);
3936 else if (plci->data_sent)
3938 channel_xmit_xon (plci);
3939 plci->data_sent = false;
3940 plci->NL.XNum = 1;
3941 data_rc (plci, ch);
3942 if (plci->internal_command)
3943 control_rc (plci, req, rc, ch, 0, true);
3945 else
3947 channel_xmit_xon (plci);
3948 control_rc (plci, req, rc, ch, 0, true);
3953 else
3956 If REMOVE request was sent then we have to wait until
3957 return code with Id set to zero arrives.
3958 All other return codes should be ignored.
3960 if (req == REMOVE)
3962 if (e->Id)
3964 dbug(1,dprintf("cancel RC in REMOVE state"));
3965 return;
3967 plci->sig_remove_id = 0;
3969 plci->sig_req = 0;
3970 if (plci->sig_global_req)
3972 global_req = plci->sig_global_req;
3973 plci->sig_global_req = 0;
3974 if (rc != ASSIGN_OK)
3975 e->Id = 0;
3976 channel_xmit_xon (plci);
3977 control_rc (plci, 0, rc, ch, global_req, false);
3979 else
3981 channel_xmit_xon (plci);
3982 control_rc (plci, req, rc, ch, 0, false);
3986 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3987 same callback. Also if new XDI and protocol code used then jump
3988 direct to finish.
3990 if (no_cancel_rc) {
3991 channel_xmit_xon(plci);
3992 goto capi_callback_suffix;
3996 channel_xmit_xon(plci);
3998 if (e->Ind) {
3999 if (e->user[0] &0x8000) {
4000 byte Ind = e->Ind & 0x0f;
4001 byte Ch = e->IndCh;
4002 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4003 (a->ch_flow_plci[Ch] == plci->Id)) {
4004 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4005 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4007 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4009 nl_ind(plci);
4010 if ((e->RNR != 1) &&
4011 (a->ch_flow_plci[Ch] == plci->Id) &&
4012 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4013 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4014 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4016 } else {
4017 sig_ind(plci);
4019 e->Ind = 0;
4022 capi_callback_suffix:
4024 while (!plci->req_in
4025 && !plci->internal_command
4026 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4028 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4030 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4032 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4033 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4034 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4035 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4036 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4038 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4039 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4041 else
4043 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4045 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4047 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4048 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4050 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4052 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4053 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4055 i = api_put (appl, m);
4056 if (i != 0)
4058 if (m->header.command == _DATA_B3_R)
4060 TransmitBufferFree (appl, (byte *)(m->info.data_b3_req.Data));
4062 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4063 break;
4066 if (plci->li_notify_update)
4068 plci->li_notify_update = false;
4069 mixer_notify_update (plci, false);
4073 send_data(plci);
4074 send_req(plci);
4078 void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4080 dword Id;
4081 dword rId;
4082 word Number;
4083 word Info=0;
4084 word i;
4085 word ncci;
4086 DIVA_CAPI_ADAPTER * a;
4087 APPL * appl;
4088 PLCI * rplci;
4089 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4090 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4092 if (!plci) {
4093 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4094 return;
4096 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4097 if(plci->req_in!=plci->req_out)
4099 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4101 dbug(1,dprintf("req_1return"));
4102 return;
4104 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4106 plci->req_in = plci->req_in_start = plci->req_out = 0;
4107 dbug(1,dprintf("control_rc"));
4109 appl = plci->appl;
4110 a = plci->adapter;
4111 ncci = a->ch_ncci[ch];
4112 if(appl)
4114 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4115 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4116 Number = plci->number;
4117 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));
4118 dbug(1,dprintf("channels=0x%x",plci->channels));
4119 if (plci_remove_check(plci))
4120 return;
4121 if(req==REMOVE && rc==ASSIGN_OK)
4123 sig_req(plci,HANGUP,0);
4124 sig_req(plci,REMOVE,0);
4125 send_req(plci);
4127 if(plci->command)
4129 switch(plci->command)
4131 case C_HOLD_REQ:
4132 dbug(1,dprintf("HoldRC=0x%x",rc));
4133 SSparms[1] = (byte)S_HOLD;
4134 if(rc!=OK)
4136 plci->SuppState = IDLE;
4137 Info = 0x2001;
4139 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4140 break;
4142 case C_RETRIEVE_REQ:
4143 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4144 SSparms[1] = (byte)S_RETRIEVE;
4145 if(rc!=OK)
4147 plci->SuppState = CALL_HELD;
4148 Info = 0x2001;
4150 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4151 break;
4153 case _INFO_R:
4154 dbug(1,dprintf("InfoRC=0x%x",rc));
4155 if(rc!=OK) Info=_WRONG_STATE;
4156 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4157 break;
4159 case _CONNECT_R:
4160 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4161 if (plci->State == INC_DIS_PENDING)
4162 break;
4163 if(plci->Sig.Id!=0xff)
4165 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4166 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4168 dbug(1,dprintf("No more IDs/Call_Req failed"));
4169 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4170 plci_remove(plci);
4171 plci->State = IDLE;
4172 break;
4174 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4175 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4177 else /* D-ch activation */
4179 if (rc != ASSIGN_OK)
4181 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4182 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4183 plci_remove(plci);
4184 plci->State = IDLE;
4185 break;
4187 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4188 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4189 plci->State = INC_ACT_PENDING;
4191 break;
4193 case _CONNECT_I|RESPONSE:
4194 if (plci->State != INC_DIS_PENDING)
4195 plci->State = INC_CON_ACCEPT;
4196 break;
4198 case _DISCONNECT_R:
4199 if (plci->State == INC_DIS_PENDING)
4200 break;
4201 if(plci->Sig.Id!=0xff)
4203 plci->State = OUTG_DIS_PENDING;
4204 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4206 break;
4208 case SUSPEND_REQ:
4209 break;
4211 case RESUME_REQ:
4212 break;
4214 case _CONNECT_B3_R:
4215 if(rc!=OK)
4217 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4218 break;
4220 ncci = get_ncci (plci, ch, 0);
4221 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4222 plci->channels++;
4223 if(req==N_RESET)
4225 a->ncci_state[ncci] = INC_ACT_PENDING;
4226 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4227 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4229 else
4231 a->ncci_state[ncci] = OUTG_CON_PENDING;
4232 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4234 break;
4236 case _CONNECT_B3_I|RESPONSE:
4237 break;
4239 case _RESET_B3_R:
4240 /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4241 break;
4243 case _DISCONNECT_B3_R:
4244 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4245 break;
4247 case _MANUFACTURER_R:
4248 break;
4250 case PERM_LIST_REQ:
4251 if(rc!=OK)
4253 Info = _WRONG_IDENTIFIER;
4254 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4255 plci_remove(plci);
4257 else
4258 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4259 break;
4261 default:
4262 break;
4264 plci->command = 0;
4266 else if (plci->internal_command)
4268 switch(plci->internal_command)
4270 case BLOCK_PLCI:
4271 return;
4273 case GET_MWI_STATE:
4274 if(rc==OK) /* command supported, wait for indication */
4276 return;
4278 plci_remove(plci);
4279 break;
4281 /* Get Supported Services */
4282 case GETSERV_REQ_PEND:
4283 if(rc==OK) /* command supported, wait for indication */
4285 break;
4287 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4288 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4289 plci_remove(plci);
4290 break;
4292 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4293 case INTERR_NUMBERS_REQ_PEND:
4294 case CF_START_PEND: /* Call Forwarding Start pending */
4295 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4296 case CCBS_REQUEST_REQ_PEND:
4297 case CCBS_DEACTIVATE_REQ_PEND:
4298 case CCBS_INTERROGATE_REQ_PEND:
4299 switch(plci->internal_command)
4301 case INTERR_DIVERSION_REQ_PEND:
4302 SSparms[1] = S_INTERROGATE_DIVERSION;
4303 break;
4304 case INTERR_NUMBERS_REQ_PEND:
4305 SSparms[1] = S_INTERROGATE_NUMBERS;
4306 break;
4307 case CF_START_PEND:
4308 SSparms[1] = S_CALL_FORWARDING_START;
4309 break;
4310 case CF_STOP_PEND:
4311 SSparms[1] = S_CALL_FORWARDING_STOP;
4312 break;
4313 case CCBS_REQUEST_REQ_PEND:
4314 SSparms[1] = S_CCBS_REQUEST;
4315 break;
4316 case CCBS_DEACTIVATE_REQ_PEND:
4317 SSparms[1] = S_CCBS_DEACTIVATE;
4318 break;
4319 case CCBS_INTERROGATE_REQ_PEND:
4320 SSparms[1] = S_CCBS_INTERROGATE;
4321 break;
4323 if(global_req==ASSIGN)
4325 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4326 return;
4328 if(!plci->appl) break;
4329 if(rc==ISDN_GUARD_REJ)
4331 Info = _CAPI_GUARD_ERROR;
4333 else if(rc!=OK)
4335 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4337 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4338 plci->number,"wws",Info,(word)3,SSparms);
4339 if(Info) plci_remove(plci);
4340 break;
4342 /* 3pty conference pending */
4343 case PTY_REQ_PEND:
4344 if(!plci->relatedPTYPLCI) break;
4345 rplci = plci->relatedPTYPLCI;
4346 SSparms[1] = plci->ptyState;
4347 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4348 if(rplci->tel) rId|=EXT_CONTROLLER;
4349 if(rc!=OK)
4351 Info = 0x300E; /* not supported */
4352 plci->relatedPTYPLCI = NULL;
4353 plci->ptyState = 0;
4355 sendf(rplci->appl,
4356 _FACILITY_R|CONFIRM,
4357 rId,
4358 plci->number,
4359 "wws",Info,(word)3,SSparms);
4360 break;
4362 /* Explicit Call Transfer pending */
4363 case ECT_REQ_PEND:
4364 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4365 if(!plci->relatedPTYPLCI) break;
4366 rplci = plci->relatedPTYPLCI;
4367 SSparms[1] = S_ECT;
4368 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4369 if(rplci->tel) rId|=EXT_CONTROLLER;
4370 if(rc!=OK)
4372 Info = 0x300E; /* not supported */
4373 plci->relatedPTYPLCI = NULL;
4374 plci->ptyState = 0;
4376 sendf(rplci->appl,
4377 _FACILITY_R|CONFIRM,
4378 rId,
4379 plci->number,
4380 "wws",Info,(word)3,SSparms);
4381 break;
4383 case _MANUFACTURER_R:
4384 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4385 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4387 dbug(1,dprintf("No more IDs"));
4388 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4389 plci_remove(plci); /* after codec init, internal codec commands pending */
4391 break;
4393 case _CONNECT_R:
4394 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4395 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4397 dbug(1,dprintf("No more IDs"));
4398 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4399 plci_remove(plci); /* after codec init, internal codec commands pending */
4401 break;
4403 case PERM_COD_HOOK: /* finished with Hook_Ind */
4404 return;
4406 case PERM_COD_CALL:
4407 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4408 plci->internal_command = PERM_COD_CONN_PEND;
4409 return;
4411 case PERM_COD_ASSIGN:
4412 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4413 if(rc!=ASSIGN_OK) break;
4414 sig_req(plci,CALL_REQ,0);
4415 send_req(plci);
4416 plci->internal_command = PERM_COD_CALL;
4417 return;
4419 /* Null Call Reference Request pending */
4420 case C_NCR_FAC_REQ:
4421 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4422 if(global_req==ASSIGN)
4424 if(rc==ASSIGN_OK)
4426 return;
4428 else
4430 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4431 appl->NullCREnable = false;
4432 plci_remove(plci);
4435 else if(req==NCR_FACILITY)
4437 if(rc==OK)
4439 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4441 else
4443 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4444 appl->NullCREnable = false;
4446 plci_remove(plci);
4448 break;
4450 case HOOK_ON_REQ:
4451 if(plci->channels)
4453 if(a->ncci_state[ncci]==CONNECTED)
4455 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4456 cleanup_ncci_data (plci, ncci);
4457 nl_req_ncci(plci,N_DISC,(byte)ncci);
4459 break;
4461 break;
4463 case HOOK_OFF_REQ:
4464 if (plci->State == INC_DIS_PENDING)
4465 break;
4466 sig_req(plci,CALL_REQ,0);
4467 send_req(plci);
4468 plci->State=OUTG_CON_PENDING;
4469 break;
4472 case MWI_ACTIVATE_REQ_PEND:
4473 case MWI_DEACTIVATE_REQ_PEND:
4474 if(global_req == ASSIGN && rc==ASSIGN_OK)
4476 dbug(1,dprintf("MWI_REQ assigned"));
4477 return;
4479 else if(rc!=OK)
4481 if(rc==WRONG_IE)
4483 Info = 0x2007; /* Illegal message parameter coding */
4484 dbug(1,dprintf("MWI_REQ invalid parameter"));
4486 else
4488 Info = 0x300B; /* not supported */
4489 dbug(1,dprintf("MWI_REQ not supported"));
4491 /* 0x3010: Request not allowed in this state */
4492 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4495 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4497 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4499 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4501 if(plci->cr_enquiry)
4503 sendf(plci->appl,
4504 _FACILITY_R|CONFIRM,
4505 Id&0xf,
4506 plci->number,
4507 "wws",Info,(word)3,SSparms);
4508 if(rc!=OK) plci_remove(plci);
4510 else
4512 sendf(plci->appl,
4513 _FACILITY_R|CONFIRM,
4515 plci->number,
4516 "wws",Info,(word)3,SSparms);
4518 break;
4520 case CONF_BEGIN_REQ_PEND:
4521 case CONF_ADD_REQ_PEND:
4522 case CONF_SPLIT_REQ_PEND:
4523 case CONF_DROP_REQ_PEND:
4524 case CONF_ISOLATE_REQ_PEND:
4525 case CONF_REATTACH_REQ_PEND:
4526 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4527 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4528 rplci = plci;
4529 rId = Id;
4530 switch(plci->internal_command)
4532 case CONF_BEGIN_REQ_PEND:
4533 SSparms[1] = S_CONF_BEGIN;
4534 break;
4535 case CONF_ADD_REQ_PEND:
4536 SSparms[1] = S_CONF_ADD;
4537 rplci = plci->relatedPTYPLCI;
4538 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4539 break;
4540 case CONF_SPLIT_REQ_PEND:
4541 SSparms[1] = S_CONF_SPLIT;
4542 break;
4543 case CONF_DROP_REQ_PEND:
4544 SSparms[1] = S_CONF_DROP;
4545 break;
4546 case CONF_ISOLATE_REQ_PEND:
4547 SSparms[1] = S_CONF_ISOLATE;
4548 break;
4549 case CONF_REATTACH_REQ_PEND:
4550 SSparms[1] = S_CONF_REATTACH;
4551 break;
4554 if(rc!=OK)
4556 Info = 0x300E; /* not supported */
4557 plci->relatedPTYPLCI = NULL;
4558 plci->ptyState = 0;
4560 sendf(rplci->appl,
4561 _FACILITY_R|CONFIRM,
4562 rId,
4563 plci->number,
4564 "wws",Info,(word)3,SSparms);
4565 break;
4567 case VSWITCH_REQ_PEND:
4568 if(rc!=OK)
4570 if(plci->relatedPTYPLCI)
4572 plci->relatedPTYPLCI->vswitchstate=0;
4573 plci->relatedPTYPLCI->vsprot=0;
4574 plci->relatedPTYPLCI->vsprotdialect=0;
4576 plci->vswitchstate=0;
4577 plci->vsprot=0;
4578 plci->vsprotdialect=0;
4580 else
4582 if(plci->relatedPTYPLCI &&
4583 plci->vswitchstate==1 &&
4584 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4585 plci->vswitchstate=3;
4587 break;
4589 /* Call Deflection Request pending (SSCT) */
4590 case CD_REQ_PEND:
4591 SSparms[1] = S_CALL_DEFLECTION;
4592 if(rc!=OK)
4594 Info = 0x300E; /* not supported */
4595 plci->appl->CDEnable = 0;
4597 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4598 plci->number,"wws",Info,(word)3,SSparms);
4599 break;
4601 case RTP_CONNECT_B3_REQ_COMMAND_2:
4602 if (rc == OK)
4604 ncci = get_ncci (plci, ch, 0);
4605 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4606 plci->channels++;
4607 a->ncci_state[ncci] = OUTG_CON_PENDING;
4610 default:
4611 if (plci->internal_command_queue[0])
4613 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4614 if (plci->internal_command)
4615 return;
4617 break;
4619 next_internal_command (Id, plci);
4622 else /* appl==0 */
4624 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4625 if(plci->tel) Id|=EXT_CONTROLLER;
4627 switch(plci->internal_command)
4629 case BLOCK_PLCI:
4630 return;
4632 case START_L1_SIG_ASSIGN_PEND:
4633 case REM_L1_SIG_ASSIGN_PEND:
4634 if(global_req == ASSIGN)
4636 break;
4638 else
4640 dbug(1,dprintf("***L1 Req rem PLCI"));
4641 plci->internal_command = 0;
4642 sig_req(plci,REMOVE,0);
4643 send_req(plci);
4645 break;
4647 /* Call Deflection Request pending, just no appl ptr assigned */
4648 case CD_REQ_PEND:
4649 SSparms[1] = S_CALL_DEFLECTION;
4650 if(rc!=OK)
4652 Info = 0x300E; /* not supported */
4654 for(i=0; i<max_appl; i++)
4656 if(application[i].CDEnable)
4658 if(!application[i].Id) application[i].CDEnable = 0;
4659 else
4661 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4662 plci->number,"wws",Info,(word)3,SSparms);
4663 if(Info) application[i].CDEnable = 0;
4667 plci->internal_command = 0;
4668 break;
4670 case PERM_COD_HOOK: /* finished with Hook_Ind */
4671 return;
4673 case PERM_COD_CALL:
4674 plci->internal_command = PERM_COD_CONN_PEND;
4675 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4676 return;
4678 case PERM_COD_ASSIGN:
4679 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4680 plci->internal_command = 0;
4681 if(rc!=ASSIGN_OK) break;
4682 plci->internal_command = PERM_COD_CALL;
4683 sig_req(plci,CALL_REQ,0);
4684 send_req(plci);
4685 return;
4687 case LISTEN_SIG_ASSIGN_PEND:
4688 if(rc == ASSIGN_OK)
4690 plci->internal_command = 0;
4691 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4692 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4693 sig_req(plci,INDICATE_REQ,0);
4694 send_req(plci);
4696 else
4698 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4699 a->listen_active--;
4700 plci_remove(plci);
4701 plci->State = IDLE;
4703 break;
4705 case USELAW_REQ:
4706 if(global_req == ASSIGN)
4708 if (rc==ASSIGN_OK)
4710 sig_req(plci,LAW_REQ,0);
4711 send_req(plci);
4712 dbug(1,dprintf("Auto-Law assigned"));
4714 else
4716 dbug(1,dprintf("Auto-Law assign failed"));
4717 a->automatic_law = 3;
4718 plci->internal_command = 0;
4719 a->automatic_lawPLCI = NULL;
4721 break;
4723 else if(req == LAW_REQ && rc==OK)
4725 dbug(1,dprintf("Auto-Law initiated"));
4726 a->automatic_law = 2;
4727 plci->internal_command = 0;
4729 else
4731 dbug(1,dprintf("Auto-Law not supported"));
4732 a->automatic_law = 3;
4733 plci->internal_command = 0;
4734 sig_req(plci,REMOVE,0);
4735 send_req(plci);
4736 a->automatic_lawPLCI = NULL;
4738 break;
4740 plci_remove_check(plci);
4744 void data_rc(PLCI * plci, byte ch)
4746 dword Id;
4747 DIVA_CAPI_ADAPTER * a;
4748 NCCI *ncci_ptr;
4749 DATA_B3_DESC *data;
4750 word ncci;
4752 if (plci->appl)
4754 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4755 a = plci->adapter;
4756 ncci = a->ch_ncci[ch];
4757 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4759 ncci_ptr = &(a->ncci[ncci]);
4760 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4761 if (ncci_ptr->data_pending)
4763 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4764 if (!(data->Flags &4) && a->ncci_state[ncci])
4766 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4767 if(plci->tel) Id|=EXT_CONTROLLER;
4768 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4769 "ww",data->Handle,0);
4771 (ncci_ptr->data_out)++;
4772 if (ncci_ptr->data_out == MAX_DATA_B3)
4773 ncci_ptr->data_out = 0;
4774 (ncci_ptr->data_pending)--;
4780 void data_ack(PLCI * plci, byte ch)
4782 dword Id;
4783 DIVA_CAPI_ADAPTER * a;
4784 NCCI *ncci_ptr;
4785 word ncci;
4787 a = plci->adapter;
4788 ncci = a->ch_ncci[ch];
4789 ncci_ptr = &(a->ncci[ncci]);
4790 if (ncci_ptr->data_ack_pending)
4792 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4794 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4795 if(plci->tel) Id|=EXT_CONTROLLER;
4796 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4797 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4799 (ncci_ptr->data_ack_out)++;
4800 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4801 ncci_ptr->data_ack_out = 0;
4802 (ncci_ptr->data_ack_pending)--;
4806 void sig_ind(PLCI * plci)
4808 dword x_Id;
4809 dword Id;
4810 dword rId;
4811 word Number = 0;
4812 word i;
4813 word cip;
4814 dword cip_mask;
4815 byte *ie;
4816 DIVA_CAPI_ADAPTER * a;
4817 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4818 #define MAXPARMSIDS 31
4819 byte * parms[MAXPARMSIDS];
4820 byte * add_i[4];
4821 byte * multi_fac_parms[MAX_MULTI_IE];
4822 byte * multi_pi_parms [MAX_MULTI_IE];
4823 byte * multi_ssext_parms [MAX_MULTI_IE];
4824 byte * multi_CiPN_parms [MAX_MULTI_IE];
4826 byte * multi_vswitch_parms [MAX_MULTI_IE];
4828 byte ai_len;
4829 byte *esc_chi = "";
4830 byte *esc_law = "";
4831 byte *pty_cai = "";
4832 byte *esc_cr = "";
4833 byte *esc_profile = "";
4835 byte facility[256];
4836 PLCI * tplci = NULL;
4837 byte chi[] = "\x02\x18\x01";
4838 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4839 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4840 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4841 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4842 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4843 /* (see Info_Mask Bit 4, first IE. then the message type) */
4844 word parms_id[] =
4845 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4846 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4847 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4848 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4849 /* 14 FTY repl by ESC_CHI */
4850 /* 18 PI repl by ESC_LAW */
4851 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4852 word multi_fac_id[] = {1, FTY};
4853 word multi_pi_id[] = {1, PI};
4854 word multi_CiPN_id[] = {1, OAD};
4855 word multi_ssext_id[] = {1, ESC_SSEXT};
4857 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4859 byte * cau;
4860 word ncci;
4861 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4862 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4863 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4864 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4865 byte force_mt_info = false;
4866 byte dir;
4867 dword d;
4868 word w;
4870 a = plci->adapter;
4871 Id = ((word)plci->Id<<8)|a->Id;
4872 PUT_WORD(&SS_Ind[4],0x0000);
4874 if (plci->sig_remove_id)
4876 plci->Sig.RNR = 2; /* discard */
4877 dbug(1,dprintf("SIG discard while remove pending"));
4878 return;
4880 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4881 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4882 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4883 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4885 plci->Sig.RNR = 1;
4886 return;
4888 if(plci->Sig.Ind==HANGUP && plci->channels)
4890 plci->Sig.RNR = 1;
4891 plci->hangup_flow_ctrl_timer++;
4892 /* recover the network layer after timeout */
4893 if(plci->hangup_flow_ctrl_timer==100)
4895 dbug(1,dprintf("Exceptional disc"));
4896 plci->Sig.RNR = 0;
4897 plci->hangup_flow_ctrl_timer = 0;
4898 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4900 if (a->ncci_plci[ncci] == plci->Id)
4902 cleanup_ncci_data (plci, ncci);
4903 if(plci->channels)plci->channels--;
4904 if (plci->appl)
4905 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4908 if (plci->appl)
4909 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4910 plci_remove(plci);
4911 plci->State=IDLE;
4913 return;
4916 /* do first parse the info with no OAD in, because OAD will be converted */
4917 /* first the multiple facility IE, then mult. progress ind. */
4918 /* then the parameters for the info_ind + conn_ind */
4919 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4920 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4921 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4923 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4925 IndParse(plci,parms_id,parms,0);
4926 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4927 esc_chi = parms[14];
4928 esc_law = parms[18];
4929 pty_cai = parms[24];
4930 esc_cr = parms[25];
4931 esc_profile = parms[27];
4932 if(esc_cr[0] && plci)
4934 if(plci->cr_enquiry && plci->appl)
4936 plci->cr_enquiry = false;
4937 /* d = MANU_ID */
4938 /* w = m_command */
4939 /* b = total length */
4940 /* b = indication type */
4941 /* b = length of all IEs */
4942 /* b = IE1 */
4943 /* S = IE1 length + cont. */
4944 /* b = IE2 */
4945 /* S = IE2 lenght + cont. */
4946 sendf(plci->appl,
4947 _MANUFACTURER_I,
4950 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4951 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);
4954 /* create the additional info structure */
4955 add_i[1] = parms[15]; /* KEY of additional info */
4956 add_i[2] = parms[11]; /* UUI of additional info */
4957 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4959 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4960 /* indication returns by the card if requested by the function */
4961 /* AutomaticLaw() after driver init */
4962 if (a->automatic_law<4)
4964 if(esc_law[0]){
4965 if(esc_law[2]){
4966 dbug(0,dprintf("u-Law selected"));
4967 a->u_law = 1;
4969 else {
4970 dbug(0,dprintf("a-Law selected"));
4971 a->u_law = 0;
4973 a->automatic_law = 4;
4974 if(plci==a->automatic_lawPLCI) {
4975 plci->internal_command = 0;
4976 sig_req(plci,REMOVE,0);
4977 send_req(plci);
4978 a->automatic_lawPLCI = NULL;
4981 if (esc_profile[0])
4983 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4984 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4985 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4986 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4988 a->profile.Global_Options &= 0x000000ffL;
4989 a->profile.B1_Protocols &= 0x000003ffL;
4990 a->profile.B2_Protocols &= 0x00001fdfL;
4991 a->profile.B3_Protocols &= 0x000000b7L;
4993 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4994 GL_BCHANNEL_OPERATION_SUPPORTED;
4995 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4996 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4997 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4998 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4999 a->man_profile.private_options = 0;
5001 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5003 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5004 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5008 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5009 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5010 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5011 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5014 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5015 a->man_profile.private_options |= 1L << PRIVATE_T38;
5018 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5019 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5022 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5023 a->man_profile.private_options |= 1L << PRIVATE_V18;
5026 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5027 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5030 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5031 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5034 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5035 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5038 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5039 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5042 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5043 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5046 else
5048 a->profile.Global_Options &= 0x0000007fL;
5049 a->profile.B1_Protocols &= 0x000003dfL;
5050 a->profile.B2_Protocols &= 0x00001adfL;
5051 a->profile.B3_Protocols &= 0x000000b7L;
5052 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5054 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5055 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5057 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5059 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5060 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5061 UnMapController (a->Id), a->profile.Global_Options,
5062 a->profile.B1_Protocols, a->profile.B2_Protocols,
5063 a->profile.B3_Protocols, a->manufacturer_features));
5065 /* codec plci for the handset/hook state support is just an internal id */
5066 if(plci!=a->AdvCodecPLCI)
5068 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5069 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5070 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5071 SendInfo(plci,Id, parms, force_mt_info);
5073 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5077 /* switch the codec to the b-channel */
5078 if(esc_chi[0] && plci && !plci->SuppState){
5079 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5080 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5081 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5082 if(plci->tel==ADV_VOICE && plci->appl) {
5083 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5087 if(plci->appl) Number = plci->appl->Number++;
5089 switch(plci->Sig.Ind) {
5090 /* Response to Get_Supported_Services request */
5091 case S_SUPPORTED:
5092 dbug(1,dprintf("S_Supported"));
5093 if(!plci->appl) break;
5094 if(pty_cai[0]==4)
5096 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5098 else
5100 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5102 PUT_WORD (&CF_Ind[1], 0);
5103 PUT_WORD (&CF_Ind[4], 0);
5104 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5105 plci_remove(plci);
5106 break;
5108 /* Supplementary Service rejected */
5109 case S_SERVICE_REJ:
5110 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5111 if(!pty_cai[0]) break;
5112 switch (pty_cai[5])
5114 case ECT_EXECUTE:
5115 case THREE_PTY_END:
5116 case THREE_PTY_BEGIN:
5117 if(!plci->relatedPTYPLCI) break;
5118 tplci = plci->relatedPTYPLCI;
5119 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5120 if(tplci->tel) rId|=EXT_CONTROLLER;
5121 if(pty_cai[5]==ECT_EXECUTE)
5123 PUT_WORD(&SS_Ind[1],S_ECT);
5125 plci->vswitchstate=0;
5126 plci->relatedPTYPLCI->vswitchstate=0;
5129 else
5131 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5133 if(pty_cai[2]!=0xff)
5135 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5137 else
5139 PUT_WORD(&SS_Ind[4],0x300E);
5141 plci->relatedPTYPLCI = NULL;
5142 plci->ptyState = 0;
5143 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5144 break;
5146 case CALL_DEFLECTION:
5147 if(pty_cai[2]!=0xff)
5149 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5151 else
5153 PUT_WORD(&SS_Ind[4],0x300E);
5155 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5156 for(i=0; i<max_appl; i++)
5158 if(application[i].CDEnable)
5160 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5161 application[i].CDEnable = false;
5164 break;
5166 case DEACTIVATION_DIVERSION:
5167 case ACTIVATION_DIVERSION:
5168 case DIVERSION_INTERROGATE_CFU:
5169 case DIVERSION_INTERROGATE_CFB:
5170 case DIVERSION_INTERROGATE_CFNR:
5171 case DIVERSION_INTERROGATE_NUM:
5172 case CCBS_REQUEST:
5173 case CCBS_DEACTIVATE:
5174 case CCBS_INTERROGATE:
5175 if(!plci->appl) break;
5176 if(pty_cai[2]!=0xff)
5178 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5180 else
5182 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5184 switch (pty_cai[5])
5186 case DEACTIVATION_DIVERSION:
5187 dbug(1,dprintf("Deact_Div"));
5188 Interr_Err_Ind[0]=0x9;
5189 Interr_Err_Ind[3]=0x6;
5190 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5191 break;
5192 case ACTIVATION_DIVERSION:
5193 dbug(1,dprintf("Act_Div"));
5194 Interr_Err_Ind[0]=0x9;
5195 Interr_Err_Ind[3]=0x6;
5196 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5197 break;
5198 case DIVERSION_INTERROGATE_CFU:
5199 case DIVERSION_INTERROGATE_CFB:
5200 case DIVERSION_INTERROGATE_CFNR:
5201 dbug(1,dprintf("Interr_Div"));
5202 Interr_Err_Ind[0]=0xa;
5203 Interr_Err_Ind[3]=0x7;
5204 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5205 break;
5206 case DIVERSION_INTERROGATE_NUM:
5207 dbug(1,dprintf("Interr_Num"));
5208 Interr_Err_Ind[0]=0xa;
5209 Interr_Err_Ind[3]=0x7;
5210 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5211 break;
5212 case CCBS_REQUEST:
5213 dbug(1,dprintf("CCBS Request"));
5214 Interr_Err_Ind[0]=0xd;
5215 Interr_Err_Ind[3]=0xa;
5216 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5217 break;
5218 case CCBS_DEACTIVATE:
5219 dbug(1,dprintf("CCBS Deactivate"));
5220 Interr_Err_Ind[0]=0x9;
5221 Interr_Err_Ind[3]=0x6;
5222 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5223 break;
5224 case CCBS_INTERROGATE:
5225 dbug(1,dprintf("CCBS Interrogate"));
5226 Interr_Err_Ind[0]=0xb;
5227 Interr_Err_Ind[3]=0x8;
5228 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5229 break;
5231 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5232 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5233 plci_remove(plci);
5234 break;
5235 case ACTIVATION_MWI:
5236 case DEACTIVATION_MWI:
5237 if(pty_cai[5]==ACTIVATION_MWI)
5239 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5241 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5243 if(pty_cai[2]!=0xff)
5245 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5247 else
5249 PUT_WORD(&SS_Ind[4],0x300E);
5252 if(plci->cr_enquiry)
5254 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5255 plci_remove(plci);
5257 else
5259 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5261 break;
5262 case CONF_ADD: /* ERROR */
5263 case CONF_BEGIN:
5264 case CONF_DROP:
5265 case CONF_ISOLATE:
5266 case CONF_REATTACH:
5267 CONF_Ind[0]=9;
5268 CONF_Ind[3]=6;
5269 switch(pty_cai[5])
5271 case CONF_BEGIN:
5272 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5273 plci->ptyState = 0;
5274 break;
5275 case CONF_DROP:
5276 CONF_Ind[0]=5;
5277 CONF_Ind[3]=2;
5278 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5279 plci->ptyState = CONNECTED;
5280 break;
5281 case CONF_ISOLATE:
5282 CONF_Ind[0]=5;
5283 CONF_Ind[3]=2;
5284 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5285 plci->ptyState = CONNECTED;
5286 break;
5287 case CONF_REATTACH:
5288 CONF_Ind[0]=5;
5289 CONF_Ind[3]=2;
5290 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5291 plci->ptyState = CONNECTED;
5292 break;
5293 case CONF_ADD:
5294 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5295 plci->relatedPTYPLCI = NULL;
5296 tplci=plci->relatedPTYPLCI;
5297 if(tplci) tplci->ptyState = CONNECTED;
5298 plci->ptyState = CONNECTED;
5299 break;
5302 if(pty_cai[2]!=0xff)
5304 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5306 else
5308 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5309 within the required time */
5312 PUT_DWORD(&CONF_Ind[6],0x0);
5313 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5314 break;
5316 break;
5318 /* Supplementary Service indicates success */
5319 case S_SERVICE:
5320 dbug(1,dprintf("Service_Ind"));
5321 PUT_WORD (&CF_Ind[4], 0);
5322 switch (pty_cai[5])
5324 case THREE_PTY_END:
5325 case THREE_PTY_BEGIN:
5326 case ECT_EXECUTE:
5327 if(!plci->relatedPTYPLCI) break;
5328 tplci = plci->relatedPTYPLCI;
5329 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5330 if(tplci->tel) rId|=EXT_CONTROLLER;
5331 if(pty_cai[5]==ECT_EXECUTE)
5333 PUT_WORD(&SS_Ind[1],S_ECT);
5335 if(plci->vswitchstate!=3)
5338 plci->ptyState = IDLE;
5339 plci->relatedPTYPLCI = NULL;
5340 plci->ptyState = 0;
5344 dbug(1,dprintf("ECT OK"));
5345 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5350 else
5352 switch (plci->ptyState)
5354 case S_3PTY_BEGIN:
5355 plci->ptyState = CONNECTED;
5356 dbug(1,dprintf("3PTY ON"));
5357 break;
5359 case S_3PTY_END:
5360 plci->ptyState = IDLE;
5361 plci->relatedPTYPLCI = NULL;
5362 plci->ptyState = 0;
5363 dbug(1,dprintf("3PTY OFF"));
5364 break;
5366 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5367 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5369 break;
5371 case CALL_DEFLECTION:
5372 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5373 for(i=0; i<max_appl; i++)
5375 if(application[i].CDEnable)
5377 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5378 application[i].CDEnable = false;
5381 break;
5383 case DEACTIVATION_DIVERSION:
5384 case ACTIVATION_DIVERSION:
5385 if(!plci->appl) break;
5386 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5387 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5388 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5389 plci_remove(plci);
5390 break;
5392 case DIVERSION_INTERROGATE_CFU:
5393 case DIVERSION_INTERROGATE_CFB:
5394 case DIVERSION_INTERROGATE_CFNR:
5395 case DIVERSION_INTERROGATE_NUM:
5396 case CCBS_REQUEST:
5397 case CCBS_DEACTIVATE:
5398 case CCBS_INTERROGATE:
5399 if(!plci->appl) break;
5400 switch (pty_cai[5])
5402 case DIVERSION_INTERROGATE_CFU:
5403 case DIVERSION_INTERROGATE_CFB:
5404 case DIVERSION_INTERROGATE_CFNR:
5405 dbug(1,dprintf("Interr_Div"));
5406 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5407 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5408 break;
5409 case DIVERSION_INTERROGATE_NUM:
5410 dbug(1,dprintf("Interr_Num"));
5411 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5412 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5413 break;
5414 case CCBS_REQUEST:
5415 dbug(1,dprintf("CCBS Request"));
5416 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5417 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5418 break;
5419 case CCBS_DEACTIVATE:
5420 dbug(1,dprintf("CCBS Deactivate"));
5421 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5422 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5423 break;
5424 case CCBS_INTERROGATE:
5425 dbug(1,dprintf("CCBS Interrogate"));
5426 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5427 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5428 break;
5430 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5431 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5432 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5433 plci_remove(plci);
5434 break;
5436 case ACTIVATION_MWI:
5437 case DEACTIVATION_MWI:
5438 if(pty_cai[5]==ACTIVATION_MWI)
5440 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5442 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5443 if(plci->cr_enquiry)
5445 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5446 plci_remove(plci);
5448 else
5450 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5452 break;
5453 case MWI_INDICATION:
5454 if(pty_cai[0]>=0x12)
5456 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5457 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5458 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5459 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5461 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5463 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5464 plci_remove(plci);
5465 return;
5467 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5468 pty_cai[0]=0;
5470 else
5472 for(i=0; i<max_appl; i++)
5474 if(a->Notification_Mask[i]&SMASK_MWI)
5476 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5477 pty_cai[0]=0;
5482 if(!pty_cai[0])
5483 { /* acknowledge */
5484 facility[2]= 0; /* returncode */
5486 else facility[2]= 0xff;
5488 else
5490 /* reject */
5491 facility[2]= 0xff; /* returncode */
5493 facility[0]= 2;
5494 facility[1]= MWI_RESPONSE; /* Function */
5495 add_p(plci,CAI,facility);
5496 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5497 sig_req(plci,S_SERVICE,0);
5498 send_req(plci);
5499 plci->command = 0;
5500 next_internal_command (Id, plci);
5501 break;
5502 case CONF_ADD: /* OK */
5503 case CONF_BEGIN:
5504 case CONF_DROP:
5505 case CONF_ISOLATE:
5506 case CONF_REATTACH:
5507 case CONF_PARTYDISC:
5508 CONF_Ind[0]=9;
5509 CONF_Ind[3]=6;
5510 switch(pty_cai[5])
5512 case CONF_BEGIN:
5513 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5514 if(pty_cai[0]==6)
5516 d=pty_cai[6];
5517 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5519 else
5521 PUT_DWORD(&CONF_Ind[6],0x0);
5523 break;
5524 case CONF_ISOLATE:
5525 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5526 CONF_Ind[0]=5;
5527 CONF_Ind[3]=2;
5528 break;
5529 case CONF_REATTACH:
5530 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5531 CONF_Ind[0]=5;
5532 CONF_Ind[3]=2;
5533 break;
5534 case CONF_DROP:
5535 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5536 CONF_Ind[0]=5;
5537 CONF_Ind[3]=2;
5538 break;
5539 case CONF_ADD:
5540 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5541 d=pty_cai[6];
5542 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5543 tplci=plci->relatedPTYPLCI;
5544 if(tplci) tplci->ptyState = CONNECTED;
5545 break;
5546 case CONF_PARTYDISC:
5547 CONF_Ind[0]=7;
5548 CONF_Ind[3]=4;
5549 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5550 d=pty_cai[6];
5551 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5552 break;
5554 plci->ptyState = CONNECTED;
5555 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5556 break;
5557 case CCBS_INFO_RETAIN:
5558 case CCBS_ERASECALLLINKAGEID:
5559 case CCBS_STOP_ALERTING:
5560 CONF_Ind[0]=5;
5561 CONF_Ind[3]=2;
5562 switch(pty_cai[5])
5564 case CCBS_INFO_RETAIN:
5565 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5566 break;
5567 case CCBS_STOP_ALERTING:
5568 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5569 break;
5570 case CCBS_ERASECALLLINKAGEID:
5571 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5572 CONF_Ind[0]=7;
5573 CONF_Ind[3]=4;
5574 CONF_Ind[6]=0;
5575 CONF_Ind[7]=0;
5576 break;
5578 w=pty_cai[6];
5579 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5581 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5583 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5585 else
5587 for(i=0; i<max_appl; i++)
5588 if(a->Notification_Mask[i]&SMASK_CCBS)
5589 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5591 break;
5593 break;
5594 case CALL_HOLD_REJ:
5595 cau = parms[7];
5596 if(cau)
5598 i = _L3_CAUSE | cau[2];
5599 if(cau[2]==0) i = 0x3603;
5601 else
5603 i = 0x3603;
5605 PUT_WORD(&SS_Ind[1],S_HOLD);
5606 PUT_WORD(&SS_Ind[4],i);
5607 if(plci->SuppState == HOLD_REQUEST)
5609 plci->SuppState = IDLE;
5610 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5612 break;
5614 case CALL_HOLD_ACK:
5615 if(plci->SuppState == HOLD_REQUEST)
5617 plci->SuppState = CALL_HELD;
5618 CodecIdCheck(a, plci);
5619 start_internal_command (Id, plci, hold_save_command);
5621 break;
5623 case CALL_RETRIEVE_REJ:
5624 cau = parms[7];
5625 if(cau)
5627 i = _L3_CAUSE | cau[2];
5628 if(cau[2]==0) i = 0x3603;
5630 else
5632 i = 0x3603;
5634 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5635 PUT_WORD(&SS_Ind[4],i);
5636 if(plci->SuppState == RETRIEVE_REQUEST)
5638 plci->SuppState = CALL_HELD;
5639 CodecIdCheck(a, plci);
5640 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5642 break;
5644 case CALL_RETRIEVE_ACK:
5645 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5646 if(plci->SuppState == RETRIEVE_REQUEST)
5648 plci->SuppState = IDLE;
5649 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5650 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5651 if(plci->tel)
5653 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5654 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5655 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5656 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5658 dbug(1,dprintf("Get B-ch"));
5659 start_internal_command (Id, plci, retrieve_restore_command);
5661 else
5662 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5664 else
5665 start_internal_command (Id, plci, retrieve_restore_command);
5667 break;
5669 case INDICATE_IND:
5670 if(plci->State != LISTENING) {
5671 sig_req(plci,HANGUP,0);
5672 send_req(plci);
5673 break;
5675 cip = find_cip(a,parms[4],parms[6]);
5676 cip_mask = 1L<<cip;
5677 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5678 clear_c_ind_mask (plci);
5679 if (!remove_started && !a->adapter_disabled)
5681 set_c_ind_mask_bit (plci, MAX_APPL);
5682 group_optimization(a, plci);
5683 for(i=0; i<max_appl; i++) {
5684 if(application[i].Id
5685 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5686 && CPN_filter_ok(parms[0],a,i)
5687 && test_group_ind_mask_bit (plci, i) ) {
5688 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5689 set_c_ind_mask_bit (plci, i);
5690 dump_c_ind_mask (plci);
5691 plci->State = INC_CON_PENDING;
5692 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5693 CALL_DIR_IN | CALL_DIR_ANSWER;
5694 if(esc_chi[0]) {
5695 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5696 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5698 /* if a listen on the ext controller is done, check if hook states */
5699 /* are supported or if just a on board codec must be activated */
5700 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5701 if(a->profile.Global_Options & HANDSET)
5702 plci->tel = ADV_VOICE;
5703 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5704 plci->tel = CODEC;
5705 if(plci->tel) Id|=EXT_CONTROLLER;
5706 a->codec_listen[i] = plci;
5709 sendf(&application[i],_CONNECT_I,Id,0,
5710 "wSSSSSSSbSSSSS", cip, /* CIP */
5711 parms[0], /* CalledPartyNumber */
5712 multi_CiPN_parms[0], /* CallingPartyNumber */
5713 parms[2], /* CalledPartySubad */
5714 parms[3], /* CallingPartySubad */
5715 parms[4], /* BearerCapability */
5716 parms[5], /* LowLC */
5717 parms[6], /* HighLC */
5718 ai_len, /* nested struct add_i */
5719 add_i[0], /* B channel info */
5720 add_i[1], /* keypad facility */
5721 add_i[2], /* user user data */
5722 add_i[3], /* nested facility */
5723 multi_CiPN_parms[1] /* second CiPN(SCR) */
5725 SendSSExtInd(&application[i],
5726 plci,
5728 multi_ssext_parms);
5729 SendSetupInfo(&application[i],
5730 plci,
5732 parms,
5733 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5736 clear_c_ind_mask_bit (plci, MAX_APPL);
5737 dump_c_ind_mask (plci);
5739 if(c_ind_mask_empty (plci)) {
5740 sig_req(plci,HANGUP,0);
5741 send_req(plci);
5742 plci->State = IDLE;
5744 plci->notifiedcall = 0;
5745 a->listen_active--;
5746 listen_check(a);
5747 break;
5749 case CALL_PEND_NOTIFY:
5750 plci->notifiedcall = 1;
5751 listen_check(a);
5752 break;
5754 case CALL_IND:
5755 case CALL_CON:
5756 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5758 if(plci->internal_command==PERM_COD_CONN_PEND)
5760 if(plci->State==ADVANCED_VOICE_NOSIG)
5762 dbug(1,dprintf("***Codec OK"));
5763 if(a->AdvSignalPLCI)
5765 tplci = a->AdvSignalPLCI;
5766 if(tplci->spoofed_msg)
5768 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5769 tplci->command = 0;
5770 tplci->internal_command = 0;
5771 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5772 switch (tplci->spoofed_msg)
5774 case CALL_RES:
5775 tplci->command = _CONNECT_I|RESPONSE;
5776 api_load_msg (&tplci->saved_msg, saved_parms);
5777 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5778 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5780 /* early B3 connect (CIP mask bit 9) no release after a disc */
5781 add_p(tplci,LLI,"\x01\x01");
5783 add_s(tplci, CONN_NR, &saved_parms[2]);
5784 add_s(tplci, LLC, &saved_parms[4]);
5785 add_ai(tplci, &saved_parms[5]);
5786 tplci->State = INC_CON_ACCEPT;
5787 sig_req(tplci, CALL_RES,0);
5788 send_req(tplci);
5789 break;
5791 case AWAITING_SELECT_B:
5792 dbug(1,dprintf("Select_B continue"));
5793 start_internal_command (x_Id, tplci, select_b_command);
5794 break;
5796 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5797 if(!tplci->Sig.Id)
5799 dbug(1,dprintf("No SigID!"));
5800 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5801 plci_remove(tplci);
5802 break;
5804 tplci->command = _MANUFACTURER_R;
5805 api_load_msg (&tplci->saved_msg, saved_parms);
5806 dir = saved_parms[2].info[0];
5807 if(dir==1) {
5808 sig_req(tplci,CALL_REQ,0);
5810 else if(!dir){
5811 sig_req(tplci,LISTEN_REQ,0);
5813 send_req(tplci);
5814 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5815 break;
5817 case (CALL_REQ|AWAITING_MANUF_CON):
5818 sig_req(tplci,CALL_REQ,0);
5819 send_req(tplci);
5820 break;
5822 case CALL_REQ:
5823 if(!tplci->Sig.Id)
5825 dbug(1,dprintf("No SigID!"));
5826 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5827 plci_remove(tplci);
5828 break;
5830 tplci->command = _CONNECT_R;
5831 api_load_msg (&tplci->saved_msg, saved_parms);
5832 add_s(tplci,CPN,&saved_parms[1]);
5833 add_s(tplci,DSA,&saved_parms[3]);
5834 add_ai(tplci,&saved_parms[9]);
5835 sig_req(tplci,CALL_REQ,0);
5836 send_req(tplci);
5837 break;
5839 case CALL_RETRIEVE:
5840 tplci->command = C_RETRIEVE_REQ;
5841 sig_req(tplci,CALL_RETRIEVE,0);
5842 send_req(tplci);
5843 break;
5845 tplci->spoofed_msg = 0;
5846 if (tplci->internal_command == 0)
5847 next_internal_command (x_Id, tplci);
5850 next_internal_command (Id, plci);
5851 break;
5853 dbug(1,dprintf("***Codec Hook Init Req"));
5854 plci->internal_command = PERM_COD_HOOK;
5855 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5856 sig_req(plci,TEL_CTRL,0);
5857 send_req(plci);
5860 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5861 && plci->State!=INC_ACT_PENDING)
5863 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5864 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5866 chi[2] = plci->b_channel;
5867 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5869 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5870 plci->State = INC_ACT_PENDING;
5872 break;
5874 case TEL_CTRL:
5875 Number = 0;
5876 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5877 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5878 switch (ie[1]&0x91) {
5879 case 0x80: /* hook off */
5880 case 0x81:
5881 if(plci->internal_command==PERM_COD_HOOK)
5883 dbug(1,dprintf("init:hook_off"));
5884 plci->hook_state = ie[1];
5885 next_internal_command (Id, plci);
5886 break;
5888 else /* ignore doubled hook indications */
5890 if( ((plci->hook_state)&0xf0)==0x80)
5892 dbug(1,dprintf("ignore hook"));
5893 break;
5895 plci->hook_state = ie[1]&0x91;
5897 /* check for incoming call pending */
5898 /* and signal '+'.Appl must decide */
5899 /* with connect_res if call must */
5900 /* accepted or not */
5901 for(i=0, tplci=NULL;i<max_appl;i++){
5902 if(a->codec_listen[i]
5903 && (a->codec_listen[i]->State==INC_CON_PENDING
5904 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5905 tplci = a->codec_listen[i];
5906 tplci->appl = &application[i];
5909 /* no incoming call, do outgoing call */
5910 /* and signal '+' if outg. setup */
5911 if(!a->AdvSignalPLCI && !tplci){
5912 if((i=get_plci(a))) {
5913 a->AdvSignalPLCI = &a->plci[i-1];
5914 tplci = a->AdvSignalPLCI;
5915 tplci->tel = ADV_VOICE;
5916 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5917 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5918 /* early B3 connect (CIP mask bit 9) no release after a disc */
5919 add_p(tplci,LLI,"\x01\x01");
5921 add_p(tplci, CAI, voice_cai);
5922 add_p(tplci, OAD, a->TelOAD);
5923 add_p(tplci, OSA, a->TelOSA);
5924 add_p(tplci,SHIFT|6,NULL);
5925 add_p(tplci,SIN,"\x02\x01\x00");
5926 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5927 sig_req(tplci,ASSIGN,DSIG_ID);
5928 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5929 a->AdvSignalPLCI->command = 0;
5930 tplci->appl = a->AdvSignalAppl;
5931 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5932 send_req(tplci);
5937 if(!tplci) break;
5938 Id = ((word)tplci->Id<<8)|a->Id;
5939 Id|=EXT_CONTROLLER;
5940 sendf(tplci->appl,
5941 _FACILITY_I,
5944 "ws", (word)0, "\x01+");
5945 break;
5947 case 0x90: /* hook on */
5948 case 0x91:
5949 if(plci->internal_command==PERM_COD_HOOK)
5951 dbug(1,dprintf("init:hook_on"));
5952 plci->hook_state = ie[1]&0x91;
5953 next_internal_command (Id, plci);
5954 break;
5956 else /* ignore doubled hook indications */
5958 if( ((plci->hook_state)&0xf0)==0x90) break;
5959 plci->hook_state = ie[1]&0x91;
5961 /* hangup the adv. voice call and signal '-' to the appl */
5962 if(a->AdvSignalPLCI) {
5963 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5964 if(plci->tel) Id|=EXT_CONTROLLER;
5965 sendf(a->AdvSignalAppl,
5966 _FACILITY_I,
5969 "ws", (word)0, "\x01-");
5970 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5971 a->AdvSignalPLCI->command = 0;
5972 sig_req(a->AdvSignalPLCI,HANGUP,0);
5973 send_req(a->AdvSignalPLCI);
5975 break;
5978 break;
5980 case RESUME:
5981 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5982 PUT_WORD(&resume_cau[4],GOOD);
5983 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5984 break;
5986 case SUSPEND:
5987 clear_c_ind_mask (plci);
5989 if (plci->NL.Id && !plci->nl_remove_id) {
5990 mixer_remove (plci);
5991 nl_req_ncci(plci,REMOVE,0);
5993 if (!plci->sig_remove_id) {
5994 plci->internal_command = 0;
5995 sig_req(plci,REMOVE,0);
5997 send_req(plci);
5998 if(!plci->channels) {
5999 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6000 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6002 break;
6004 case SUSPEND_REJ:
6005 break;
6007 case HANGUP:
6008 plci->hangup_flow_ctrl_timer=0;
6009 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6010 cau = parms[7];
6011 if(cau) {
6012 i = _L3_CAUSE | cau[2];
6013 if(cau[2]==0) i = 0;
6014 else if(cau[2]==8) i = _L1_ERROR;
6015 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6016 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6018 else {
6019 i = _L3_ERROR;
6022 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6024 for(i=0; i<max_appl; i++)
6026 if(test_c_ind_mask_bit (plci, i))
6027 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6030 else
6032 clear_c_ind_mask (plci);
6034 if(!plci->appl)
6036 if (plci->State == LISTENING)
6038 plci->notifiedcall=0;
6039 a->listen_active--;
6041 plci->State = INC_DIS_PENDING;
6042 if(c_ind_mask_empty (plci))
6044 plci->State = IDLE;
6045 if (plci->NL.Id && !plci->nl_remove_id)
6047 mixer_remove (plci);
6048 nl_req_ncci(plci,REMOVE,0);
6050 if (!plci->sig_remove_id)
6052 plci->internal_command = 0;
6053 sig_req(plci,REMOVE,0);
6055 send_req(plci);
6058 else
6060 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6061 /* result in a second HANGUP! Don't generate another */
6062 /* DISCONNECT */
6063 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6065 if(plci->State==RESUMING)
6067 PUT_WORD(&resume_cau[4],i);
6068 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6070 plci->State = INC_DIS_PENDING;
6071 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6074 break;
6076 case SSEXT_IND:
6077 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6078 break;
6080 case VSWITCH_REQ:
6081 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6082 break;
6083 case VSWITCH_IND:
6084 if(plci->relatedPTYPLCI &&
6085 plci->vswitchstate==3 &&
6086 plci->relatedPTYPLCI->vswitchstate==3 &&
6087 parms[MAXPARMSIDS-1][0])
6089 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6090 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6091 send_req(plci->relatedPTYPLCI);
6093 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6094 break;
6100 static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6102 word i;
6103 byte * ie;
6104 word Info_Number;
6105 byte * Info_Element;
6106 word Info_Mask = 0;
6108 dbug(1,dprintf("SetupInfo"));
6110 for(i=0; i<MAXPARMSIDS; i++) {
6111 ie = parms[i];
6112 Info_Number = 0;
6113 Info_Element = ie;
6114 if(ie[0]) {
6115 switch(i) {
6116 case 0:
6117 dbug(1,dprintf("CPN "));
6118 Info_Number = 0x0070;
6119 Info_Mask = 0x80;
6120 Info_Sent_Flag = true;
6121 break;
6122 case 8: /* display */
6123 dbug(1,dprintf("display(%d)",i));
6124 Info_Number = 0x0028;
6125 Info_Mask = 0x04;
6126 Info_Sent_Flag = true;
6127 break;
6128 case 16: /* Channel Id */
6129 dbug(1,dprintf("CHI"));
6130 Info_Number = 0x0018;
6131 Info_Mask = 0x100;
6132 Info_Sent_Flag = true;
6133 mixer_set_bchannel_id (plci, Info_Element);
6134 break;
6135 case 19: /* Redirected Number */
6136 dbug(1,dprintf("RDN"));
6137 Info_Number = 0x0074;
6138 Info_Mask = 0x400;
6139 Info_Sent_Flag = true;
6140 break;
6141 case 20: /* Redirected Number extended */
6142 dbug(1,dprintf("RDX"));
6143 Info_Number = 0x0073;
6144 Info_Mask = 0x400;
6145 Info_Sent_Flag = true;
6146 break;
6147 case 22: /* Redirecing Number */
6148 dbug(1,dprintf("RIN"));
6149 Info_Number = 0x0076;
6150 Info_Mask = 0x400;
6151 Info_Sent_Flag = true;
6152 break;
6153 default:
6154 Info_Number = 0;
6155 break;
6159 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6160 Info_Number = 0x8000 |5;
6161 Info_Mask = 0x10;
6162 Info_Element = "";
6165 if(Info_Sent_Flag && Info_Number){
6166 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6167 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6174 void SendInfo(PLCI * plci, dword Id, byte * * parms, byte iesent)
6176 word i;
6177 word j;
6178 word k;
6179 byte * ie;
6180 word Info_Number;
6181 byte * Info_Element;
6182 word Info_Mask = 0;
6183 static byte charges[5] = {4,0,0,0,0};
6184 static byte cause[] = {0x02,0x80,0x00};
6185 APPL *appl;
6187 dbug(1,dprintf("InfoParse "));
6190 !plci->appl
6191 && !plci->State
6192 && plci->Sig.Ind!=NCR_FACILITY
6195 dbug(1,dprintf("NoParse "));
6196 return;
6198 cause[2] = 0;
6199 for(i=0; i<MAXPARMSIDS; i++) {
6200 ie = parms[i];
6201 Info_Number = 0;
6202 Info_Element = ie;
6203 if(ie[0]) {
6204 switch(i) {
6205 case 0:
6206 dbug(1,dprintf("CPN "));
6207 Info_Number = 0x0070;
6208 Info_Mask = 0x80;
6209 break;
6210 case 7: /* ESC_CAU */
6211 dbug(1,dprintf("cau(0x%x)",ie[2]));
6212 Info_Number = 0x0008;
6213 Info_Mask = 0x00;
6214 cause[2] = ie[2];
6215 Info_Element = NULL;
6216 break;
6217 case 8: /* display */
6218 dbug(1,dprintf("display(%d)",i));
6219 Info_Number = 0x0028;
6220 Info_Mask = 0x04;
6221 break;
6222 case 9: /* Date display */
6223 dbug(1,dprintf("date(%d)",i));
6224 Info_Number = 0x0029;
6225 Info_Mask = 0x02;
6226 break;
6227 case 10: /* charges */
6228 for(j=0;j<4;j++) charges[1+j] = 0;
6229 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6230 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6231 Info_Number = 0x4000;
6232 Info_Mask = 0x40;
6233 Info_Element = charges;
6234 break;
6235 case 11: /* user user info */
6236 dbug(1,dprintf("uui"));
6237 Info_Number = 0x007E;
6238 Info_Mask = 0x08;
6239 break;
6240 case 12: /* congestion receiver ready */
6241 dbug(1,dprintf("clRDY"));
6242 Info_Number = 0x00B0;
6243 Info_Mask = 0x08;
6244 Info_Element = "";
6245 break;
6246 case 13: /* congestion receiver not ready */
6247 dbug(1,dprintf("clNRDY"));
6248 Info_Number = 0x00BF;
6249 Info_Mask = 0x08;
6250 Info_Element = "";
6251 break;
6252 case 15: /* Keypad Facility */
6253 dbug(1,dprintf("KEY"));
6254 Info_Number = 0x002C;
6255 Info_Mask = 0x20;
6256 break;
6257 case 16: /* Channel Id */
6258 dbug(1,dprintf("CHI"));
6259 Info_Number = 0x0018;
6260 Info_Mask = 0x100;
6261 mixer_set_bchannel_id (plci, Info_Element);
6262 break;
6263 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6264 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6265 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6266 Info_Number = 0x0008;
6267 Info_Mask = 0x01;
6268 if(cause[2] != ie[2]) Info_Element = cause;
6269 break;
6270 case 19: /* Redirected Number */
6271 dbug(1,dprintf("RDN"));
6272 Info_Number = 0x0074;
6273 Info_Mask = 0x400;
6274 break;
6275 case 22: /* Redirecing Number */
6276 dbug(1,dprintf("RIN"));
6277 Info_Number = 0x0076;
6278 Info_Mask = 0x400;
6279 break;
6280 case 23: /* Notification Indicator */
6281 dbug(1,dprintf("NI"));
6282 Info_Number = (word)NI;
6283 Info_Mask = 0x210;
6284 break;
6285 case 26: /* Call State */
6286 dbug(1,dprintf("CST"));
6287 Info_Number = (word)CST;
6288 Info_Mask = 0x01; /* do with cause i.e. for now */
6289 break;
6290 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6291 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6292 Info_Number = 0x8000 |ie[3];
6293 if(iesent) Info_Mask = 0xffff;
6294 else Info_Mask = 0x10;
6295 Info_Element = "";
6296 break;
6297 default:
6298 Info_Number = 0;
6299 Info_Mask = 0;
6300 Info_Element = "";
6301 break;
6305 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6307 for(j=0; j<max_appl; j++)
6309 appl = &application[j];
6310 if(Info_Number
6311 && appl->Id
6312 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6314 dbug(1,dprintf("NCR_Ind"));
6315 iesent=true;
6316 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6320 else if(!plci->appl)
6321 { /* overlap receiving broadcast */
6322 if(Info_Number==CPN
6323 || Info_Number==KEY
6324 || Info_Number==NI
6325 || Info_Number==DSP
6326 || Info_Number==UUI )
6328 for(j=0; j<max_appl; j++)
6330 if(test_c_ind_mask_bit (plci, j))
6332 dbug(1,dprintf("Ovl_Ind"));
6333 iesent=true;
6334 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6338 } /* all other signalling states */
6339 else if(Info_Number
6340 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6342 dbug(1,dprintf("Std_Ind"));
6343 iesent=true;
6344 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6350 byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse)
6352 word i;
6353 word j;
6354 byte * ie;
6355 word Info_Number;
6356 byte * Info_Element;
6357 APPL *appl;
6358 word Info_Mask = 0;
6359 byte iesent=0;
6362 !plci->appl
6363 && !plci->State
6364 && plci->Sig.Ind!=NCR_FACILITY
6365 && !setupParse
6368 dbug(1,dprintf("NoM-IEParse "));
6369 return 0;
6371 dbug(1,dprintf("M-IEParse "));
6373 for(i=0; i<MAX_MULTI_IE; i++)
6375 ie = parms[i];
6376 Info_Number = 0;
6377 Info_Element = ie;
6378 if(ie[0])
6380 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6381 Info_Number = (word)ie_type;
6382 Info_Mask = (word)info_mask;
6385 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6387 for(j=0; j<max_appl; j++)
6389 appl = &application[j];
6390 if(Info_Number
6391 && appl->Id
6392 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6394 iesent = true;
6395 dbug(1,dprintf("Mlt_NCR_Ind"));
6396 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6400 else if(!plci->appl && Info_Number)
6401 { /* overlap receiving broadcast */
6402 for(j=0; j<max_appl; j++)
6404 if(test_c_ind_mask_bit (plci, j))
6406 iesent = true;
6407 dbug(1,dprintf("Mlt_Ovl_Ind"));
6408 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6411 } /* all other signalling states */
6412 else if(Info_Number
6413 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6415 iesent = true;
6416 dbug(1,dprintf("Mlt_Std_Ind"));
6417 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6420 return iesent;
6423 static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6425 word i;
6426 /* Format of multi_ssext_parms[i][]:
6427 0 byte length
6428 1 byte SSEXTIE
6429 2 byte SSEXT_REQ/SSEXT_IND
6430 3 byte length
6431 4 word SSExtCommand
6432 6... Params
6435 plci
6436 && plci->State
6437 && plci->Sig.Ind!=NCR_FACILITY
6439 for(i=0;i<MAX_MULTI_IE;i++)
6441 if(parms[i][0]<6) continue;
6442 if(parms[i][2]==SSEXT_REQ) continue;
6444 if(appl)
6446 parms[i][0]=0; /* kill it */
6447 sendf(appl,_MANUFACTURER_I,
6450 "dwS",
6451 _DI_MANU_ID,
6452 _DI_SSEXT_CTRL,
6453 &parms[i][3]);
6455 else if(plci->appl)
6457 parms[i][0]=0; /* kill it */
6458 sendf(plci->appl,_MANUFACTURER_I,
6461 "dwS",
6462 _DI_MANU_ID,
6463 _DI_SSEXT_CTRL,
6464 &parms[i][3]);
6469 void nl_ind(PLCI * plci)
6471 byte ch;
6472 word ncci;
6473 dword Id;
6474 DIVA_CAPI_ADAPTER * a;
6475 word NCCIcode;
6476 APPL * APPLptr;
6477 word count;
6478 word Num;
6479 word i, ncpi_state;
6480 byte len, ncci_state;
6481 word msg;
6482 word info = 0;
6483 word fax_feature_bits;
6484 byte fax_send_edata_ack;
6485 static byte v120_header_buffer[2 + 3];
6486 static word fax_info[] = {
6487 0, /* T30_SUCCESS */
6488 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6489 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6490 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6491 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6492 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6493 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6494 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6495 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6496 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6497 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6498 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6499 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6500 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6501 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6502 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6503 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6504 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6505 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6506 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6507 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6508 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6511 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6512 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6520 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6521 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6522 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6523 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6524 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6525 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6526 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6527 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6531 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6532 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6533 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6536 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6539 static word rtp_info[] = {
6540 GOOD, /* RTP_SUCCESS */
6541 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6544 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6546 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6547 0x00000000, 0x00000000, 0x00000000, 0x00000000
6550 ch = plci->NL.IndCh;
6551 a = plci->adapter;
6552 ncci = a->ch_ncci[ch];
6553 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6554 if(plci->tel) Id|=EXT_CONTROLLER;
6555 APPLptr = plci->appl;
6556 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",
6557 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6559 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6561 if (plci->nl_remove_id)
6563 plci->NL.RNR = 2; /* discard */
6564 dbug(1,dprintf("NL discard while remove pending"));
6565 return;
6567 if((plci->NL.Ind &0x0f)==N_CONNECT)
6569 if(plci->State==INC_DIS_PENDING
6570 || plci->State==OUTG_DIS_PENDING
6571 || plci->State==IDLE)
6573 plci->NL.RNR = 2; /* discard */
6574 dbug(1,dprintf("discard n_connect"));
6575 return;
6577 if(plci->State < INC_ACT_PENDING)
6579 plci->NL.RNR = 1; /* flow control */
6580 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6581 return;
6585 if(!APPLptr) /* no application or invalid data */
6586 { /* while reloading the DSP */
6587 dbug(1,dprintf("discard1"));
6588 plci->NL.RNR = 2;
6589 return;
6592 if (((plci->NL.Ind &0x0f) == N_UDATA)
6593 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6594 || (plci->B2_prot == 7)
6595 || (plci->B3_prot == 7)) )
6597 plci->ncpi_buffer[0] = 0;
6599 ncpi_state = plci->ncpi_state;
6600 if (plci->NL.complete == 1)
6602 byte * data = &plci->NL.RBuffer->P[0];
6604 if ((plci->NL.RBuffer->length >= 12)
6605 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6606 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6608 word conn_opt, ncpi_opt = 0x00;
6609 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6611 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6612 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6613 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6614 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6616 data++; /* indication code */
6617 data += 2; /* timestamp */
6618 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6619 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6620 data++; /* connected norm */
6621 conn_opt = GET_WORD(data);
6622 data += 2; /* connected options */
6624 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6626 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6628 ncpi_opt |= MDM_NCPI_ECM_V42;
6630 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6632 ncpi_opt |= MDM_NCPI_ECM_MNP;
6634 else
6636 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6638 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6640 ncpi_opt |= MDM_NCPI_COMPRESSED;
6642 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6643 plci->ncpi_buffer[0] = 4;
6645 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6648 if (plci->B3_prot == 7)
6650 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6651 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6652 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6654 a->ncci_state[ncci] = INC_ACT_PENDING;
6655 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6656 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6660 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6661 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6662 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6663 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6666 plci->NL.RNR = 2;
6667 return;
6671 if(plci->NL.complete == 2)
6673 if (((plci->NL.Ind &0x0f) == N_UDATA)
6674 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6676 switch(plci->RData[0].P[0])
6679 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6680 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6681 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6682 break;
6683 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6684 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6685 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6686 break;
6687 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6688 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6689 break;
6690 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6691 dtmf_confirmation (Id, plci);
6692 break;
6695 case UDATA_INDICATION_MIXER_TAP_DATA:
6696 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6697 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6698 if (i != 0)
6700 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6701 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6703 break;
6706 case UDATA_INDICATION_MIXER_COEFS_SET:
6707 mixer_indication_coefs_set (Id, plci);
6708 break;
6709 case UDATA_INDICATION_XCONNECT_FROM:
6710 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6711 break;
6712 case UDATA_INDICATION_XCONNECT_TO:
6713 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714 break;
6717 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6718 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6719 break;
6723 default:
6724 break;
6727 else
6729 if ((plci->RData[0].PLength != 0)
6730 && ((plci->B2_prot == B2_V120_ASYNC)
6731 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6732 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6735 sendf(plci->appl,_DATA_B3_I,Id,0,
6736 "dwww",
6737 plci->RData[1].P,
6738 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6739 plci->RNum,
6740 plci->RFlags);
6743 else
6746 sendf(plci->appl,_DATA_B3_I,Id,0,
6747 "dwww",
6748 plci->RData[0].P,
6749 plci->RData[0].PLength,
6750 plci->RNum,
6751 plci->RFlags);
6755 return;
6758 fax_feature_bits = 0;
6759 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6760 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6761 (plci->NL.Ind &0x0f)==N_DISC ||
6762 (plci->NL.Ind &0x0f)==N_EDATA ||
6763 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6765 info = 0;
6766 plci->ncpi_buffer[0] = 0;
6767 switch (plci->B3_prot) {
6768 case 0: /*XPARENT*/
6769 case 1: /*T.90 NL*/
6770 break; /* no network control protocol info - jfr */
6771 case 2: /*ISO8202*/
6772 case 3: /*X25 DCE*/
6773 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6774 plci->ncpi_buffer[0] = (byte)(i+3);
6775 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6776 plci->ncpi_buffer[2] = 0;
6777 plci->ncpi_buffer[3] = 0;
6778 break;
6779 case 4: /*T.30 - FAX*/
6780 case 5: /*T.30 - FAX*/
6781 if(plci->NL.RLength>=sizeof(T30_INFO))
6783 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6784 len = 9;
6785 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6786 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6787 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6788 if (plci->B3_prot == 5)
6790 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6791 i |= 0x8000; /* This is not an ECM connection */
6792 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6793 i |= 0x4000; /* This is a connection with MMR compression */
6794 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6795 i |= 0x2000; /* This is a connection with MR compression */
6796 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6797 i |= 0x0004; /* More documents */
6798 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6799 i |= 0x0002; /* Fax-polling indication */
6801 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6802 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6803 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6804 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6805 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6806 plci->ncpi_buffer[len] = 0;
6807 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6809 plci->ncpi_buffer[len] = 20;
6810 for (i = 0; i < 20; i++)
6811 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6813 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6815 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6816 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6817 else
6818 info = _FAX_PROTOCOL_ERROR;
6821 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6822 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6824 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6825 while (i < plci->NL.RBuffer->length)
6826 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6829 plci->ncpi_buffer[0] = len;
6830 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6831 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6833 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6834 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6835 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6836 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6837 || (((plci->NL.Ind &0x0f) == N_EDATA)
6838 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6839 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6840 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6842 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6844 if (((plci->NL.Ind &0x0f) == N_DISC)
6845 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6846 || (((plci->NL.Ind &0x0f) == N_EDATA)
6847 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6849 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6852 break;
6854 case B3_RTP:
6855 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6857 if (plci->NL.RLength != 0)
6859 info = rtp_info[plci->NL.RBuffer->P[0]];
6860 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6861 for (i = 1; i < plci->NL.RLength; i++)
6862 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6865 break;
6868 plci->NL.RNR = 2;
6870 switch(plci->NL.Ind &0x0f) {
6871 case N_EDATA:
6872 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6874 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6875 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6876 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6878 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6879 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6880 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6881 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6882 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6883 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6885 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6886 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6887 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6888 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6889 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6890 fax_send_edata_ack = false;
6893 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6895 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6897 case EDATA_T30_DIS:
6898 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6899 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6900 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6901 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6903 a->ncci_state[ncci] = INC_ACT_PENDING;
6904 if (plci->B3_prot == 4)
6905 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6906 else
6907 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6908 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6910 break;
6912 case EDATA_T30_TRAIN_OK:
6913 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6914 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6915 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6917 if (plci->B3_prot == 4)
6918 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6919 else
6920 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6921 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6923 break;
6925 case EDATA_T30_EOP_CAPI:
6926 if (a->ncci_state[ncci] == CONNECTED)
6928 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6929 a->ncci_state[ncci] = INC_DIS_PENDING;
6930 plci->ncpi_state = 0;
6931 fax_send_edata_ack = false;
6933 break;
6936 else
6938 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6940 case EDATA_T30_TRAIN_OK:
6941 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6942 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6943 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6945 if (plci->B3_prot == 4)
6946 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6947 else
6948 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6949 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6951 break;
6954 if (fax_send_edata_ack)
6956 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6957 plci->fax_edata_ack_length = 1;
6958 start_internal_command (Id, plci, fax_edata_ack_command);
6961 else
6963 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6965 break;
6966 case N_CONNECT:
6967 if (!a->ch_ncci[ch])
6969 ncci = get_ncci (plci, ch, 0);
6970 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6972 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6973 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6975 msg = _CONNECT_B3_I;
6976 if (a->ncci_state[ncci] == IDLE)
6977 plci->channels++;
6978 else if (plci->B3_prot == 1)
6979 msg = _CONNECT_B3_T90_ACTIVE_I;
6981 a->ncci_state[ncci] = INC_CON_PENDING;
6982 if(plci->B3_prot == 4)
6983 sendf(plci->appl,msg,Id,0,"s","");
6984 else
6985 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6986 break;
6987 case N_CONNECT_ACK:
6988 dbug(1,dprintf("N_connect_Ack"));
6989 if (plci->internal_command_queue[0]
6990 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6991 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6992 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6994 (*(plci->internal_command_queue[0]))(Id, plci, 0);
6995 if (!plci->internal_command)
6996 next_internal_command (Id, plci);
6997 break;
6999 msg = _CONNECT_B3_ACTIVE_I;
7000 if (plci->B3_prot == 1)
7002 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7003 msg = _CONNECT_B3_T90_ACTIVE_I;
7004 a->ncci_state[ncci] = INC_ACT_PENDING;
7005 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7007 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7009 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7010 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7011 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7013 a->ncci_state[ncci] = INC_ACT_PENDING;
7014 if (plci->B3_prot == 4)
7015 sendf(plci->appl,msg,Id,0,"s","");
7016 else
7017 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7018 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7021 else
7023 a->ncci_state[ncci] = INC_ACT_PENDING;
7024 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7026 if (plci->adjust_b_restore)
7028 plci->adjust_b_restore = false;
7029 start_internal_command (Id, plci, adjust_b_restore);
7031 break;
7032 case N_DISC:
7033 case N_DISC_ACK:
7034 if (plci->internal_command_queue[0]
7035 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7036 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7037 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7039 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7040 if (!plci->internal_command)
7041 next_internal_command (Id, plci);
7043 ncci_state = a->ncci_state[ncci];
7044 ncci_remove (plci, ncci, false);
7046 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7047 /* channel, so we cannot store the state in ncci_state! The */
7048 /* information which channel we received a N_DISC is thus */
7049 /* stored in the inc_dis_ncci_table buffer. */
7050 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7051 plci->inc_dis_ncci_table[i] = (byte) ncci;
7053 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7054 if (!plci->channels
7055 && (plci->B1_resource == 16)
7056 && (plci->State <= CONNECTED))
7058 len = 9;
7059 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7060 PUT_WORD (&plci->ncpi_buffer[1], i);
7061 PUT_WORD (&plci->ncpi_buffer[3], 0);
7062 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7063 PUT_WORD (&plci->ncpi_buffer[5], i);
7064 PUT_WORD (&plci->ncpi_buffer[7], 0);
7065 plci->ncpi_buffer[len] = 0;
7066 plci->ncpi_buffer[0] = len;
7067 if(plci->B3_prot == 4)
7068 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7069 else
7072 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7073 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7075 plci->ncpi_buffer[++len] = 0;
7076 plci->ncpi_buffer[++len] = 0;
7077 plci->ncpi_buffer[++len] = 0;
7078 plci->ncpi_buffer[0] = len;
7081 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7083 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7084 plci->ncpi_state = 0;
7085 sig_req(plci,HANGUP,0);
7086 send_req(plci);
7087 plci->State = OUTG_DIS_PENDING;
7088 /* disc here */
7090 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7091 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7092 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7094 if (ncci_state == IDLE)
7096 if (plci->channels)
7097 plci->channels--;
7098 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7099 if(plci->State == SUSPENDING){
7100 sendf(plci->appl,
7101 _FACILITY_I,
7102 Id & 0xffffL,
7104 "ws", (word)3, "\x03\x04\x00\x00");
7105 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7107 plci_remove(plci);
7108 plci->State=IDLE;
7112 else if (plci->channels)
7114 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7115 plci->ncpi_state = 0;
7116 if ((ncci_state == OUTG_REJ_PENDING)
7117 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7119 sig_req(plci,HANGUP,0);
7120 send_req(plci);
7121 plci->State = OUTG_DIS_PENDING;
7124 break;
7125 case N_RESET:
7126 a->ncci_state[ncci] = INC_RES_PENDING;
7127 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7128 break;
7129 case N_RESET_ACK:
7130 a->ncci_state[ncci] = CONNECTED;
7131 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7132 break;
7134 case N_UDATA:
7135 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7137 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
7138 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7139 plci->NL.R = plci->RData;
7140 plci->NL.RNum = 1;
7141 return;
7143 case N_BDATA:
7144 case N_DATA:
7145 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7146 || (a->ncci_state[ncci] == IDLE)
7147 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7149 plci->NL.RNR = 2;
7150 break;
7152 if ((a->ncci_state[ncci] != CONNECTED)
7153 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7154 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7156 dbug(1,dprintf("flow control"));
7157 plci->NL.RNR = 1; /* flow control */
7158 channel_x_off (plci, ch, 0);
7159 break;
7162 NCCIcode = ncci | (((word)a->Id) << 8);
7164 /* count all buffers within the Application pool */
7165 /* belonging to the same NCCI. If this is below the */
7166 /* number of buffers available per NCCI we accept */
7167 /* this packet, otherwise we reject it */
7168 count = 0;
7169 Num = 0xffff;
7170 for(i=0; i<APPLptr->MaxBuffer; i++) {
7171 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7172 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7175 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7177 dbug(3,dprintf("Flow-Control"));
7178 plci->NL.RNR = 1;
7179 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7180 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7182 plci->NL.RNR = 2;
7183 dbug(3,dprintf("DiscardData"));
7184 } else {
7185 channel_x_off (plci, ch, 0);
7187 break;
7189 else
7191 APPLptr->NCCIDataFlowCtrlTimer = 0;
7194 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7195 if(!plci->RData[0].P) {
7196 plci->NL.RNR = 1;
7197 channel_x_off (plci, ch, 0);
7198 break;
7201 APPLptr->DataNCCI[Num] = NCCIcode;
7202 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7203 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7205 plci->RNum = Num;
7206 plci->RFlags = plci->NL.Ind>>4;
7207 plci->RData[0].PLength = APPLptr->MaxDataLength;
7208 plci->NL.R = plci->RData;
7209 if ((plci->NL.RLength != 0)
7210 && ((plci->B2_prot == B2_V120_ASYNC)
7211 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7212 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7214 plci->RData[1].P = plci->RData[0].P;
7215 plci->RData[1].PLength = plci->RData[0].PLength;
7216 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7217 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7218 plci->RData[0].PLength = 1;
7219 else
7220 plci->RData[0].PLength = 2;
7221 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7222 plci->RFlags |= 0x0010;
7223 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7224 plci->RFlags |= 0x8000;
7225 plci->NL.RNum = 2;
7227 else
7229 if((plci->NL.Ind &0x0f)==N_UDATA)
7230 plci->RFlags |= 0x0010;
7232 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7233 plci->RFlags |= 0x0001;
7235 plci->NL.RNum = 1;
7237 break;
7238 case N_DATA_ACK:
7239 data_ack (plci, ch);
7240 break;
7241 default:
7242 plci->NL.RNR = 2;
7243 break;
7247 /*------------------------------------------------------------------*/
7248 /* find a free PLCI */
7249 /*------------------------------------------------------------------*/
7251 word get_plci(DIVA_CAPI_ADAPTER * a)
7253 word i,j;
7254 PLCI * plci;
7256 dump_plcis (a);
7257 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7258 if(i==a->max_plci) {
7259 dbug(1,dprintf("get_plci: out of PLCIs"));
7260 return 0;
7262 plci = &a->plci[i];
7263 plci->Id = (byte)(i+1);
7265 plci->Sig.Id = 0;
7266 plci->NL.Id = 0;
7267 plci->sig_req = 0;
7268 plci->nl_req = 0;
7270 plci->appl = NULL;
7271 plci->relatedPTYPLCI = NULL;
7272 plci->State = IDLE;
7273 plci->SuppState = IDLE;
7274 plci->channels = 0;
7275 plci->tel = 0;
7276 plci->B1_resource = 0;
7277 plci->B2_prot = 0;
7278 plci->B3_prot = 0;
7280 plci->command = 0;
7281 plci->m_command = 0;
7282 init_internal_command_queue (plci);
7283 plci->number = 0;
7284 plci->req_in_start = 0;
7285 plci->req_in = 0;
7286 plci->req_out = 0;
7287 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7288 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7289 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7291 plci->data_sent = false;
7292 plci->send_disc = 0;
7293 plci->sig_global_req = 0;
7294 plci->sig_remove_id = 0;
7295 plci->nl_global_req = 0;
7296 plci->nl_remove_id = 0;
7297 plci->adv_nl = 0;
7298 plci->manufacturer = false;
7299 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7300 plci->spoofed_msg = 0;
7301 plci->ptyState = 0;
7302 plci->cr_enquiry = false;
7303 plci->hangup_flow_ctrl_timer = 0;
7305 plci->ncci_ring_list = 0;
7306 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7307 clear_c_ind_mask (plci);
7308 set_group_ind_mask (plci);
7309 plci->fax_connect_info_length = 0;
7310 plci->nsf_control_bits = 0;
7311 plci->ncpi_state = 0x00;
7312 plci->ncpi_buffer[0] = 0;
7314 plci->requested_options_conn = 0;
7315 plci->requested_options = 0;
7316 plci->notifiedcall = 0;
7317 plci->vswitchstate = 0;
7318 plci->vsprot = 0;
7319 plci->vsprotdialect = 0;
7320 init_b1_config (plci);
7321 dbug(1,dprintf("get_plci(%x)",plci->Id));
7322 return i+1;
7325 /*------------------------------------------------------------------*/
7326 /* put a parameter in the parameter buffer */
7327 /*------------------------------------------------------------------*/
7329 static void add_p(PLCI * plci, byte code, byte * p)
7331 word p_length;
7333 p_length = 0;
7334 if(p) p_length = p[0];
7335 add_ie(plci, code, p, p_length);
7338 /*------------------------------------------------------------------*/
7339 /* put a structure in the parameter buffer */
7340 /*------------------------------------------------------------------*/
7341 static void add_s(PLCI * plci, byte code, API_PARSE * p)
7343 if(p) add_ie(plci, code, p->info, (word)p->length);
7346 /*------------------------------------------------------------------*/
7347 /* put multiple structures in the parameter buffer */
7348 /*------------------------------------------------------------------*/
7349 static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7351 byte i;
7353 if(p){
7354 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7355 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7356 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7357 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7362 /*------------------------------------------------------------------*/
7363 /* return the channel number sent by the application in a esc_chi */
7364 /*------------------------------------------------------------------*/
7365 static byte getChannel(API_PARSE * p)
7367 byte i;
7369 if(p){
7370 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7371 if(p->info[i]==2){
7372 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7376 return 0;
7380 /*------------------------------------------------------------------*/
7381 /* put an information element in the parameter buffer */
7382 /*------------------------------------------------------------------*/
7384 static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7386 word i;
7388 if(!(code &0x80) && !p_length) return;
7390 if(plci->req_in==plci->req_in_start) {
7391 plci->req_in +=2;
7393 else {
7394 plci->req_in--;
7396 plci->RBuffer[plci->req_in++] = code;
7398 if(p) {
7399 plci->RBuffer[plci->req_in++] = (byte)p_length;
7400 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7403 plci->RBuffer[plci->req_in++] = 0;
7406 /*------------------------------------------------------------------*/
7407 /* put a unstructured data into the buffer */
7408 /*------------------------------------------------------------------*/
7410 void add_d(PLCI * plci, word length, byte * p)
7412 word i;
7414 if(plci->req_in==plci->req_in_start) {
7415 plci->req_in +=2;
7417 else {
7418 plci->req_in--;
7420 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7423 /*------------------------------------------------------------------*/
7424 /* put parameters from the Additional Info parameter in the */
7425 /* parameter buffer */
7426 /*------------------------------------------------------------------*/
7428 void add_ai(PLCI * plci, API_PARSE * ai)
7430 word i;
7431 API_PARSE ai_parms[5];
7433 for(i=0;i<5;i++) ai_parms[i].length = 0;
7435 if(!ai->length)
7436 return;
7437 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7438 return;
7440 add_s (plci,KEY,&ai_parms[1]);
7441 add_s (plci,UUI,&ai_parms[2]);
7442 add_ss(plci,FTY,&ai_parms[3]);
7445 /*------------------------------------------------------------------*/
7446 /* put parameter for b1 protocol in the parameter buffer */
7447 /*------------------------------------------------------------------*/
7449 word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7451 API_PARSE bp_parms[8];
7452 API_PARSE mdm_cfg[9];
7453 API_PARSE global_config[2];
7454 byte cai[256];
7455 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7456 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7457 word i;
7459 API_PARSE mdm_cfg_v18[4];
7460 word j, n, w;
7461 dword d;
7464 for(i=0;i<8;i++) bp_parms[i].length = 0;
7465 for(i=0;i<2;i++) global_config[i].length = 0;
7467 dbug(1,dprintf("add_b1"));
7468 api_save_msg(bp, "s", &plci->B_protocol);
7470 if(b_channel_info==2){
7471 plci->B1_resource = 0;
7472 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7473 add_p(plci, CAI, "\x01\x00");
7474 dbug(1,dprintf("Cai=1,0 (no resource)"));
7475 return 0;
7478 if(plci->tel == CODEC_PERMANENT) return 0;
7479 else if(plci->tel == CODEC){
7480 plci->B1_resource = 1;
7481 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7482 add_p(plci, CAI, "\x01\x01");
7483 dbug(1,dprintf("Cai=1,1 (Codec)"));
7484 return 0;
7486 else if(plci->tel == ADV_VOICE){
7487 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7488 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7489 voice_cai[1] = plci->B1_resource;
7490 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7491 add_p(plci, CAI, voice_cai);
7492 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7493 return 0;
7495 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7496 if (plci->call_dir & CALL_DIR_OUT)
7497 plci->call_dir |= CALL_DIR_ORIGINATE;
7498 else if (plci->call_dir & CALL_DIR_IN)
7499 plci->call_dir |= CALL_DIR_ANSWER;
7501 if(!bp->length){
7502 plci->B1_resource = 0x5;
7503 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7504 add_p(plci, CAI, "\x01\x05");
7505 return 0;
7508 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7509 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7510 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7512 bp_parms[6].length = 0;
7513 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7515 dbug(1,dprintf("b-form.!"));
7516 return _WRONG_MESSAGE_FORMAT;
7519 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7521 dbug(1,dprintf("b-form.!"));
7522 return _WRONG_MESSAGE_FORMAT;
7525 if(bp_parms[6].length)
7527 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7529 return _WRONG_MESSAGE_FORMAT;
7531 switch(GET_WORD(global_config[0].info))
7533 case 1:
7534 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7535 break;
7536 case 2:
7537 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7538 break;
7541 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7544 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7545 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7547 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7548 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7549 cai[1] = plci->B1_resource;
7550 cai[2] = 0;
7551 cai[3] = 0;
7552 cai[4] = 0;
7553 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7554 for (i = 0; i < bp_parms[3].length; i++)
7555 cai[7+i] = bp_parms[3].info[1+i];
7556 cai[0] = 6 + bp_parms[3].length;
7557 add_p(plci, CAI, cai);
7558 return 0;
7562 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7563 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7565 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567 cai[1] = plci->B1_resource;
7568 cai[2] = 0;
7569 cai[3] = 0;
7570 cai[4] = 0;
7571 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7572 cai[0] = 6;
7573 add_p(plci, CAI, cai);
7574 return 0;
7578 if ((GET_WORD(bp_parms[0].info) >= 32)
7579 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7580 && ((GET_WORD(bp_parms[0].info) != 3)
7581 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7582 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7584 return _B1_NOT_SUPPORTED;
7586 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7587 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7588 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7589 cai[0] = 6;
7590 cai[1] = plci->B1_resource;
7591 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7593 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7594 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7595 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7596 { /* B1 - modem */
7597 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7599 if (bp_parms[3].length)
7601 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7603 return (_WRONG_MESSAGE_FORMAT);
7606 cai[2] = 0; /* Bit rate for adaptation */
7608 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7610 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7611 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7612 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7613 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7615 cai[3] = 0; /* Async framing parameters */
7616 switch (GET_WORD (mdm_cfg[2].info))
7617 { /* Parity */
7618 case 1: /* odd parity */
7619 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7620 dbug(1,dprintf("MDM: odd parity"));
7621 break;
7623 case 2: /* even parity */
7624 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7625 dbug(1,dprintf("MDM: even parity"));
7626 break;
7628 default:
7629 dbug(1,dprintf("MDM: no parity"));
7630 break;
7633 switch (GET_WORD (mdm_cfg[3].info))
7634 { /* stop bits */
7635 case 1: /* 2 stop bits */
7636 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7637 dbug(1,dprintf("MDM: 2 stop bits"));
7638 break;
7640 default:
7641 dbug(1,dprintf("MDM: 1 stop bit"));
7642 break;
7645 switch (GET_WORD (mdm_cfg[1].info))
7646 { /* char length */
7647 case 5:
7648 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7649 dbug(1,dprintf("MDM: 5 bits"));
7650 break;
7652 case 6:
7653 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7654 dbug(1,dprintf("MDM: 6 bits"));
7655 break;
7657 case 7:
7658 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7659 dbug(1,dprintf("MDM: 7 bits"));
7660 break;
7662 default:
7663 dbug(1,dprintf("MDM: 8 bits"));
7664 break;
7667 cai[7] = 0; /* Line taking options */
7668 cai[8] = 0; /* Modulation negotiation options */
7669 cai[9] = 0; /* Modulation options */
7671 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7673 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7674 dbug(1, dprintf("MDM: Reverse direction"));
7677 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7679 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7680 dbug(1, dprintf("MDM: Disable retrain"));
7683 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7685 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7686 dbug(1, dprintf("MDM: Disable ring tone"));
7689 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7691 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7692 dbug(1, dprintf("MDM: 1800 guard tone"));
7694 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7696 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7697 dbug(1, dprintf("MDM: 550 guard tone"));
7700 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7702 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7703 dbug(1, dprintf("MDM: V100"));
7705 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7707 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7708 dbug(1, dprintf("MDM: IN CLASS"));
7710 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7712 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7713 dbug(1, dprintf("MDM: DISABLED"));
7715 cai[0] = 20;
7717 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7718 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7720 plci->requested_options |= 1L << PRIVATE_V18;
7722 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7723 plci->requested_options |= 1L << PRIVATE_VOWN;
7725 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7726 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7728 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7730 i = 27;
7731 if (mdm_cfg[6].length >= 4)
7733 d = GET_DWORD(&mdm_cfg[6].info[1]);
7734 cai[7] |= (byte) d; /* line taking options */
7735 cai[9] |= (byte)(d >> 8); /* modulation options */
7736 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7737 cai[++i] = (byte)(d >> 24);
7738 if (mdm_cfg[6].length >= 8)
7740 d = GET_DWORD(&mdm_cfg[6].info[5]);
7741 cai[10] |= (byte) d; /* disabled modulations mask */
7742 cai[11] |= (byte)(d >> 8);
7743 if (mdm_cfg[6].length >= 12)
7745 d = GET_DWORD(&mdm_cfg[6].info[9]);
7746 cai[12] = (byte) d; /* enabled modulations mask */
7747 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7748 cai[++i] = (byte)(d >> 16);
7749 cai[++i] = (byte)(d >> 24);
7750 cai[++i] = 0;
7751 if (mdm_cfg[6].length >= 14)
7753 w = GET_WORD(&mdm_cfg[6].info[13]);
7754 if (w != 0)
7755 PUT_WORD(&cai[13], w); /* min tx speed */
7756 if (mdm_cfg[6].length >= 16)
7758 w = GET_WORD(&mdm_cfg[6].info[15]);
7759 if (w != 0)
7760 PUT_WORD(&cai[15], w); /* max tx speed */
7761 if (mdm_cfg[6].length >= 18)
7763 w = GET_WORD(&mdm_cfg[6].info[17]);
7764 if (w != 0)
7765 PUT_WORD(&cai[17], w); /* min rx speed */
7766 if (mdm_cfg[6].length >= 20)
7768 w = GET_WORD(&mdm_cfg[6].info[19]);
7769 if (w != 0)
7770 PUT_WORD(&cai[19], w); /* max rx speed */
7771 if (mdm_cfg[6].length >= 22)
7773 w = GET_WORD(&mdm_cfg[6].info[21]);
7774 cai[23] = (byte)(-((short) w)); /* transmit level */
7775 if (mdm_cfg[6].length >= 24)
7777 w = GET_WORD(&mdm_cfg[6].info[23]);
7778 cai[22] |= (byte) w; /* info options mask */
7779 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7789 cai[27] = i - 27;
7790 i++;
7791 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7793 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7795 for (n = 0; n < 3; n++)
7797 cai[i] = (byte)(mdm_cfg_v18[n].length);
7798 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7799 cai[i+j] = mdm_cfg_v18[n].info[j];
7800 i += cai[i] + 1;
7804 cai[0] = (byte)(i - 1);
7810 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7811 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7813 if(bp_parms[3].length){
7814 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7815 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7816 case 0:
7817 case 56000:
7818 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7819 dbug(1,dprintf("56k sync HSCX"));
7820 cai[1] = 8;
7821 cai[2] = 0;
7822 cai[3] = 0;
7824 else if(GET_WORD(bp_parms[0].info)==2){
7825 dbug(1,dprintf("56k async DSP"));
7826 cai[2] = 9;
7828 break;
7829 case 50: cai[2] = 1; break;
7830 case 75: cai[2] = 1; break;
7831 case 110: cai[2] = 1; break;
7832 case 150: cai[2] = 1; break;
7833 case 200: cai[2] = 1; break;
7834 case 300: cai[2] = 1; break;
7835 case 600: cai[2] = 1; break;
7836 case 1200: cai[2] = 2; break;
7837 case 2400: cai[2] = 3; break;
7838 case 4800: cai[2] = 4; break;
7839 case 7200: cai[2] = 10; break;
7840 case 9600: cai[2] = 5; break;
7841 case 12000: cai[2] = 13; break;
7842 case 24000: cai[2] = 0; break;
7843 case 14400: cai[2] = 11; break;
7844 case 19200: cai[2] = 6; break;
7845 case 28800: cai[2] = 12; break;
7846 case 38400: cai[2] = 7; break;
7847 case 48000: cai[2] = 8; break;
7848 case 76: cai[2] = 15; break; /* 75/1200 */
7849 case 1201: cai[2] = 14; break; /* 1200/75 */
7850 case 56001: cai[2] = 9; break; /* V.110 56000 */
7852 default:
7853 return _B1_PARM_NOT_SUPPORTED;
7855 cai[3] = 0;
7856 if (cai[1] == 13) /* v.110 async */
7858 if (bp_parms[3].length >= 8)
7860 switch (GET_WORD (&bp_parms[3].info[3]))
7861 { /* char length */
7862 case 5:
7863 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7864 break;
7865 case 6:
7866 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7867 break;
7868 case 7:
7869 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7870 break;
7872 switch (GET_WORD (&bp_parms[3].info[5]))
7873 { /* Parity */
7874 case 1: /* odd parity */
7875 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7876 break;
7877 case 2: /* even parity */
7878 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7879 break;
7881 switch (GET_WORD (&bp_parms[3].info[7]))
7882 { /* stop bits */
7883 case 1: /* 2 stop bits */
7884 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7885 break;
7890 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7891 dbug(1,dprintf("V.110 default 56k sync"));
7892 cai[1] = 8;
7893 cai[2] = 0;
7894 cai[3] = 0;
7896 else {
7897 dbug(1,dprintf("V.110 default 9600 async"));
7898 cai[2] = 5;
7901 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7902 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]));
7903 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7905 add_p(plci, CAI, cai);
7906 return 0;
7909 /*------------------------------------------------------------------*/
7910 /* put parameter for b2 and B3 protocol in the parameter buffer */
7911 /*------------------------------------------------------------------*/
7913 word add_b23(PLCI * plci, API_PARSE * bp)
7915 word i, fax_control_bits;
7916 byte pos, len;
7917 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7918 API_PARSE bp_parms[8];
7919 API_PARSE * b1_config;
7920 API_PARSE * b2_config;
7921 API_PARSE b2_config_parms[8];
7922 API_PARSE * b3_config;
7923 API_PARSE b3_config_parms[6];
7924 API_PARSE global_config[2];
7926 static byte llc[3] = {2,0,0};
7927 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7928 static byte nlc[256];
7929 static byte lli[12] = {1,1};
7931 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7932 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7934 const byte llc3[] = {4,3,2,2,6,6,0};
7935 const byte header[] = {0,2,3,3,0,0,0};
7937 for(i=0;i<8;i++) bp_parms[i].length = 0;
7938 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7939 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7941 lli[0] = 1;
7942 lli[1] = 1;
7943 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7944 lli[1] |= 2;
7945 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7946 lli[1] |= 4;
7948 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7949 lli[1] |= 0x10;
7950 if (plci->rx_dma_descriptor <= 0) {
7951 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7952 if (plci->rx_dma_descriptor >= 0)
7953 plci->rx_dma_descriptor++;
7955 if (plci->rx_dma_descriptor > 0) {
7956 lli[0] = 6;
7957 lli[1] |= 0x40;
7958 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7959 lli[3] = (byte)plci->rx_dma_magic;
7960 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7961 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7962 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7966 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7967 lli[1] |= 0x20;
7970 dbug(1,dprintf("add_b23"));
7971 api_save_msg(bp, "s", &plci->B_protocol);
7973 if(!bp->length && plci->tel)
7975 plci->adv_nl = true;
7976 dbug(1,dprintf("Default adv.Nl"));
7977 add_p(plci,LLI,lli);
7978 plci->B2_prot = 1 /*XPARENT*/;
7979 plci->B3_prot = 0 /*XPARENT*/;
7980 llc[1] = 2;
7981 llc[2] = 4;
7982 add_p(plci, LLC, llc);
7983 dlc[0] = 2;
7984 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7985 add_p(plci, DLC, dlc);
7986 return 0;
7989 if(!bp->length) /*default*/
7991 dbug(1,dprintf("ret default"));
7992 add_p(plci,LLI,lli);
7993 plci->B2_prot = 0 /*X.75 */;
7994 plci->B3_prot = 0 /*XPARENT*/;
7995 llc[1] = 1;
7996 llc[2] = 4;
7997 add_p(plci, LLC, llc);
7998 dlc[0] = 2;
7999 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8000 add_p(plci, DLC, dlc);
8001 return 0;
8003 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8004 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8006 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8008 bp_parms[6].length = 0;
8009 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8011 dbug(1,dprintf("b-form.!"));
8012 return _WRONG_MESSAGE_FORMAT;
8015 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8017 dbug(1,dprintf("b-form.!"));
8018 return _WRONG_MESSAGE_FORMAT;
8021 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8023 if(GET_WORD(bp_parms[1].info)!=1
8024 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8025 plci->adv_nl = true;
8027 else if(plci->tel) return _B2_NOT_SUPPORTED;
8030 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8031 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8032 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8034 add_p(plci,LLI,lli);
8035 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8036 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8037 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8038 llc[2] = 4;
8039 add_p(plci, LLC, llc);
8040 dlc[0] = 2;
8041 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8042 dlc[3] = 3; /* Addr A */
8043 dlc[4] = 1; /* Addr B */
8044 dlc[5] = 7; /* modulo mode */
8045 dlc[6] = 7; /* window size */
8046 dlc[7] = 0; /* XID len Lo */
8047 dlc[8] = 0; /* XID len Hi */
8048 for (i = 0; i < bp_parms[4].length; i++)
8049 dlc[9+i] = bp_parms[4].info[1+i];
8050 dlc[0] = (byte)(8 + bp_parms[4].length);
8051 add_p(plci, DLC, dlc);
8052 for (i = 0; i < bp_parms[5].length; i++)
8053 nlc[1+i] = bp_parms[5].info[1+i];
8054 nlc[0] = (byte)(bp_parms[5].length);
8055 add_p(plci, NLC, nlc);
8056 return 0;
8061 if ((GET_WORD(bp_parms[1].info) >= 32)
8062 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8063 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8064 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8067 return _B2_NOT_SUPPORTED;
8069 if ((GET_WORD(bp_parms[2].info) >= 32)
8070 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8072 return _B3_NOT_SUPPORTED;
8074 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8075 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8076 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8077 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8079 return (add_modem_b23 (plci, bp_parms));
8082 add_p(plci,LLI,lli);
8084 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8085 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8086 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8088 if(bp_parms[6].length)
8090 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8092 return _WRONG_MESSAGE_FORMAT;
8094 switch(GET_WORD(global_config[0].info))
8096 case 1:
8097 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8098 break;
8099 case 2:
8100 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8101 break;
8104 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8107 if (plci->B2_prot == B2_PIAFS)
8108 llc[1] = PIAFS_CRC;
8109 else
8110 /* IMPLEMENT_PIAFS */
8112 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8113 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8115 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8117 add_p(plci, LLC, llc);
8119 dlc[0] = 2;
8120 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8121 header[GET_WORD(bp_parms[2].info)]);
8123 b1_config = &bp_parms[3];
8124 nlc[0] = 0;
8125 if(plci->B3_prot == 4
8126 || plci->B3_prot == 5)
8128 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8129 nlc[0] = sizeof(T30_INFO);
8130 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8131 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8132 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8133 if(b1_config->length>=2)
8135 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8138 b2_config = &bp_parms[4];
8141 if (llc[1] == PIAFS_CRC)
8143 if (plci->B3_prot != B3_TRANSPARENT)
8145 return _B_STACK_NOT_SUPPORTED;
8147 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8148 return _WRONG_MESSAGE_FORMAT;
8150 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8151 dlc[3] = 0; /* Addr A */
8152 dlc[4] = 0; /* Addr B */
8153 dlc[5] = 0; /* modulo mode */
8154 dlc[6] = 0; /* window size */
8155 if (b2_config->length >= 7){
8156 dlc[ 7] = 7;
8157 dlc[ 8] = 0;
8158 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8159 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8160 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8161 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8162 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8163 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8164 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8165 dlc[ 0] = 15;
8166 if(b2_config->length >= 8) { /* PIAFS control abilities */
8167 dlc[ 7] = 10;
8168 dlc[16] = 2; /* Length of PIAFS extention */
8169 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8170 dlc[18] = b2_config_parms[4].info[0]; /* value */
8171 dlc[ 0] = 18;
8174 else /* default values, 64K, variable, no compression */
8176 dlc[ 7] = 7;
8177 dlc[ 8] = 0;
8178 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8179 dlc[10] = 0x03; /* V.42bis P0 */
8180 dlc[11] = 0; /* V.42bis P0 */
8181 dlc[12] = 0; /* V.42bis P1 */
8182 dlc[13] = 0; /* V.42bis P1 */
8183 dlc[14] = 0; /* V.42bis P2 */
8184 dlc[15] = 0; /* V.42bis P2 */
8185 dlc[ 0] = 15;
8187 add_p(plci, DLC, dlc);
8189 else
8191 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8193 if (plci->B3_prot != B3_TRANSPARENT)
8194 return _B_STACK_NOT_SUPPORTED;
8196 dlc[0] = 6;
8197 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8198 dlc[3] = 0x08;
8199 dlc[4] = 0x01;
8200 dlc[5] = 127;
8201 dlc[6] = 7;
8202 if (b2_config->length != 0)
8204 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8205 return _WRONG_MESSAGE_FORMAT;
8207 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8208 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8209 if (b2_config->info[3] != 128)
8211 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8212 return _B2_PARM_NOT_SUPPORTED;
8214 dlc[5] = (byte)(b2_config->info[3] - 1);
8215 dlc[6] = b2_config->info[4];
8216 if(llc[1]==V120_V42BIS){
8217 if (b2_config->length >= 10){
8218 dlc[ 7] = 6;
8219 dlc[ 8] = 0;
8220 dlc[ 9] = b2_config_parms[4].info[0];
8221 dlc[10] = b2_config_parms[4].info[1];
8222 dlc[11] = b2_config_parms[5].info[0];
8223 dlc[12] = b2_config_parms[5].info[1];
8224 dlc[13] = b2_config_parms[6].info[0];
8225 dlc[14] = b2_config_parms[6].info[1];
8226 dlc[ 0] = 14;
8227 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8228 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8229 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8231 else {
8232 dlc[ 6] = 14;
8237 else
8239 if(b2_config->length)
8241 dbug(1,dprintf("B2-Config"));
8242 if(llc[1]==X75_V42BIS){
8243 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8245 return _WRONG_MESSAGE_FORMAT;
8248 else {
8249 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8251 return _WRONG_MESSAGE_FORMAT;
8254 /* if B2 Protocol is LAPD, b2_config structure is different */
8255 if(llc[1]==6)
8257 dlc[0] = 4;
8258 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8259 else dlc[2] = 0x01;
8260 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8262 SAPI = b2_config->info[2]; /* SAPI */
8264 dlc[1] = SAPI;
8265 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8267 dlc[3] = 127; /* Mode */
8269 else
8271 dlc[3] = 7; /* Mode */
8274 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8275 else dlc[4] = 1;
8276 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8277 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8279 else
8281 dlc[0] = (byte)(b2_config_parms[4].length+6);
8282 dlc[3] = b2_config->info[1];
8283 dlc[4] = b2_config->info[2];
8284 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8285 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8286 return _B2_PARM_NOT_SUPPORTED;
8289 dlc[5] = (byte)(b2_config->info[3]-1);
8290 dlc[6] = b2_config->info[4];
8291 if(dlc[6]>dlc[5]){
8292 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]));
8293 return _B2_PARM_NOT_SUPPORTED;
8296 if(llc[1]==X75_V42BIS) {
8297 if (b2_config->length >= 10){
8298 dlc[ 7] = 6;
8299 dlc[ 8] = 0;
8300 dlc[ 9] = b2_config_parms[4].info[0];
8301 dlc[10] = b2_config_parms[4].info[1];
8302 dlc[11] = b2_config_parms[5].info[0];
8303 dlc[12] = b2_config_parms[5].info[1];
8304 dlc[13] = b2_config_parms[6].info[0];
8305 dlc[14] = b2_config_parms[6].info[1];
8306 dlc[ 0] = 14;
8307 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8308 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8309 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8311 else {
8312 dlc[ 6] = 14;
8316 else {
8317 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8318 for(i=0; i<b2_config_parms[4].length; i++)
8319 dlc[11+i] = b2_config_parms[4].info[1+i];
8324 add_p(plci, DLC, dlc);
8326 b3_config = &bp_parms[5];
8327 if(b3_config->length)
8329 if(plci->B3_prot == 4
8330 || plci->B3_prot == 5)
8332 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8334 return _WRONG_MESSAGE_FORMAT;
8336 i = GET_WORD((byte *)(b3_config_parms[0].info));
8337 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8338 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8339 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8340 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8341 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8342 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8343 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8346 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8347 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8349 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8350 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8351 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8354 ((T30_INFO *)&nlc[1])->recording_properties =
8355 T30_RECORDING_WIDTH_ISO_A3 |
8356 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8357 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8359 if(plci->B3_prot == 5)
8361 if (i & 0x0002) /* Accept incoming fax-polling requests */
8362 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8363 if (i & 0x2000) /* Do not use MR compression */
8364 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8365 if (i & 0x4000) /* Do not use MMR compression */
8366 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8367 if (i & 0x8000) /* Do not use ECM */
8368 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8369 if (plci->fax_connect_info_length != 0)
8371 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8372 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8373 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8374 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8375 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8378 /* copy station id to NLC */
8379 for(i=0; i<20; i++)
8381 if(i<b3_config_parms[2].length)
8383 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8385 else
8387 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8390 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8391 /* copy head line to NLC */
8392 if(b3_config_parms[3].length)
8395 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8396 if (pos != 0)
8398 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8399 pos = 0;
8400 else
8402 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8403 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8404 len = (byte)b3_config_parms[2].length;
8405 if (len > 20)
8406 len = 20;
8407 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8409 for (i = 0; i < len; i++)
8410 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8411 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8412 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8417 len = (byte)b3_config_parms[3].length;
8418 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8419 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8420 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8421 nlc[0] += (byte)(pos + len);
8422 for (i = 0; i < len; i++)
8423 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8425 else
8426 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8428 plci->nsf_control_bits = 0;
8429 if(plci->B3_prot == 5)
8431 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8432 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8434 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8436 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8437 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8439 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8441 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8442 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8444 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8445 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8447 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8448 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8449 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8451 len = nlc[0];
8452 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8453 if (pos < plci->fax_connect_info_length)
8455 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8456 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8458 else
8459 nlc[++len] = 0;
8460 if (pos < plci->fax_connect_info_length)
8462 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8463 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8465 else
8466 nlc[++len] = 0;
8467 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468 & (1L << PRIVATE_FAX_NONSTANDARD))
8470 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8472 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8473 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8474 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8477 else
8479 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8481 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8482 nlc[++len] = 0;
8484 else
8486 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8487 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8488 nlc[++len] = (byte)(b3_config_parms[4].length);
8489 for (i = 0; i < b3_config_parms[4].length; i++)
8490 nlc[++len] = b3_config_parms[4].info[1+i];
8494 nlc[0] = len;
8495 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8496 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8498 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8503 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8504 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8505 for (i = 0; i < len; i++)
8506 plci->fax_connect_info_buffer[i] = nlc[1+i];
8507 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8508 i += ((T30_INFO *)&nlc[1])->head_line_len;
8509 while (i < nlc[0])
8510 plci->fax_connect_info_buffer[len++] = nlc[++i];
8511 plci->fax_connect_info_length = len;
8513 else
8515 nlc[0] = 14;
8516 if(b3_config->length!=16)
8517 return _B3_PARM_NOT_SUPPORTED;
8518 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8519 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8520 return _B3_PARM_NOT_SUPPORTED;
8521 nlc[13] = b3_config->info[13];
8522 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8523 return _B3_PARM_NOT_SUPPORTED;
8524 nlc[14] = b3_config->info[15];
8527 else
8529 if (plci->B3_prot == 4
8530 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8532 add_p(plci, NLC, nlc);
8533 return 0;
8536 /*----------------------------------------------------------------*/
8537 /* make the same as add_b23, but only for the modem related */
8538 /* L2 and L3 B-Chan protocol. */
8539 /* */
8540 /* Enabled L2 and L3 Configurations: */
8541 /* If L1 == Modem all negotiation */
8542 /* only L2 == Modem with full negotiation is allowed */
8543 /* If L1 == Modem async or sync */
8544 /* only L2 == Transparent is allowed */
8545 /* L3 == Modem or L3 == Transparent are allowed */
8546 /* B2 Configuration for modem: */
8547 /* word : enable/disable compression, bitoptions */
8548 /* B3 Configuration for modem: */
8549 /* empty */
8550 /*----------------------------------------------------------------*/
8551 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8553 static byte lli[12] = {1,1};
8554 static byte llc[3] = {2,0,0};
8555 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8556 API_PARSE mdm_config[2];
8557 word i;
8558 word b2_config = 0;
8560 for(i=0;i<2;i++) mdm_config[i].length = 0;
8561 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8563 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8564 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8565 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8566 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8568 return (_B_STACK_NOT_SUPPORTED);
8570 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8571 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8573 return (_B_STACK_NOT_SUPPORTED);
8576 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8577 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8579 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8581 if (api_parse (&bp_parms[4].info[1],
8582 (word)bp_parms[4].length, "w",
8583 mdm_config))
8585 return (_WRONG_MESSAGE_FORMAT);
8587 b2_config = GET_WORD(mdm_config[0].info);
8590 /* OK, L2 is modem */
8592 lli[0] = 1;
8593 lli[1] = 1;
8594 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8595 lli[1] |= 2;
8596 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8597 lli[1] |= 4;
8599 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8600 lli[1] |= 0x10;
8601 if (plci->rx_dma_descriptor <= 0) {
8602 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8603 if (plci->rx_dma_descriptor >= 0)
8604 plci->rx_dma_descriptor++;
8606 if (plci->rx_dma_descriptor > 0) {
8607 lli[1] |= 0x40;
8608 lli[0] = 6;
8609 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8610 lli[3] = (byte)plci->rx_dma_magic;
8611 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8612 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8613 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8617 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8618 lli[1] |= 0x20;
8621 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8622 /*V42*/ 10 : /*V42_IN*/ 9;
8623 llc[2] = 4; /* pass L3 always transparent */
8624 add_p(plci, LLI, lli);
8625 add_p(plci, LLC, llc);
8626 i = 1;
8627 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8628 i += 2;
8629 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8631 if (bp_parms[4].length)
8633 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8634 dlc[i++] = 3; /* Addr A */
8635 dlc[i++] = 1; /* Addr B */
8636 dlc[i++] = 7; /* modulo mode */
8637 dlc[i++] = 7; /* window size */
8638 dlc[i++] = 0; /* XID len Lo */
8639 dlc[i++] = 0; /* XID len Hi */
8641 if (b2_config & MDM_B2_DISABLE_V42bis)
8643 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8645 if (b2_config & MDM_B2_DISABLE_MNP)
8647 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8649 if (b2_config & MDM_B2_DISABLE_TRANS)
8651 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8653 if (b2_config & MDM_B2_DISABLE_V42)
8655 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8657 if (b2_config & MDM_B2_DISABLE_COMP)
8659 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8661 i++;
8664 else
8666 dlc[i++] = 3; /* Addr A */
8667 dlc[i++] = 1; /* Addr B */
8668 dlc[i++] = 7; /* modulo mode */
8669 dlc[i++] = 7; /* window size */
8670 dlc[i++] = 0; /* XID len Lo */
8671 dlc[i++] = 0; /* XID len Hi */
8672 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8673 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8674 DLC_MODEMPROT_DISABLE_V42_DETECT |
8675 DLC_MODEMPROT_DISABLE_COMPRESSION;
8677 dlc[0] = (byte)(i - 1);
8678 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8679 add_p(plci, DLC, dlc);
8680 return (0);
8684 /*------------------------------------------------------------------*/
8685 /* send a request for the signaling entity */
8686 /*------------------------------------------------------------------*/
8688 void sig_req(PLCI * plci, byte req, byte Id)
8690 if(!plci) return;
8691 if(plci->adapter->adapter_disabled) return;
8692 dbug(1,dprintf("sig_req(%x)",req));
8693 if (req == REMOVE)
8694 plci->sig_remove_id = plci->Sig.Id;
8695 if(plci->req_in==plci->req_in_start) {
8696 plci->req_in +=2;
8697 plci->RBuffer[plci->req_in++] = 0;
8699 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8700 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8701 plci->RBuffer[plci->req_in++] = req; /* request */
8702 plci->RBuffer[plci->req_in++] = 0; /* channel */
8703 plci->req_in_start = plci->req_in;
8706 /*------------------------------------------------------------------*/
8707 /* send a request for the network layer entity */
8708 /*------------------------------------------------------------------*/
8710 void nl_req_ncci(PLCI * plci, byte req, byte ncci)
8712 if(!plci) return;
8713 if(plci->adapter->adapter_disabled) return;
8714 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8715 if (req == REMOVE)
8717 plci->nl_remove_id = plci->NL.Id;
8718 ncci_remove (plci, 0, (byte)(ncci != 0));
8719 ncci = 0;
8721 if(plci->req_in==plci->req_in_start) {
8722 plci->req_in +=2;
8723 plci->RBuffer[plci->req_in++] = 0;
8725 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8726 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8727 plci->RBuffer[plci->req_in++] = req; /* request */
8728 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8729 plci->req_in_start = plci->req_in;
8732 void send_req(PLCI * plci)
8734 ENTITY * e;
8735 word l;
8736 /* word i; */
8738 if(!plci) return;
8739 if(plci->adapter->adapter_disabled) return;
8740 channel_xmit_xon (plci);
8742 /* if nothing to do, return */
8743 if(plci->req_in==plci->req_out) return;
8744 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8746 if(plci->nl_req || plci->sig_req) return;
8748 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8749 plci->req_out += 2;
8750 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8751 plci->req_out += l;
8752 if(plci->RBuffer[plci->req_out]==1)
8754 e = &plci->NL;
8755 plci->req_out++;
8756 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8757 e->ReqCh = plci->RBuffer[plci->req_out++];
8758 if(!(e->Id & 0x1f))
8760 e->Id = NL_ID;
8761 plci->RBuffer[plci->req_out-4] = CAI;
8762 plci->RBuffer[plci->req_out-3] = 1;
8763 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8764 plci->RBuffer[plci->req_out-1] = 0;
8765 l+=3;
8766 plci->nl_global_req = plci->nl_req;
8768 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8770 else
8772 e = &plci->Sig;
8773 if(plci->RBuffer[plci->req_out])
8774 e->Id = plci->RBuffer[plci->req_out];
8775 plci->req_out++;
8776 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8777 e->ReqCh = plci->RBuffer[plci->req_out++];
8778 if(!(e->Id & 0x1f))
8779 plci->sig_global_req = plci->sig_req;
8780 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8782 plci->XData[0].PLength = l;
8783 e->X = plci->XData;
8784 plci->adapter->request(e);
8785 dbug(1,dprintf("send_ok"));
8788 void send_data(PLCI * plci)
8790 DIVA_CAPI_ADAPTER * a;
8791 DATA_B3_DESC * data;
8792 NCCI *ncci_ptr;
8793 word ncci;
8795 if (!plci->nl_req && plci->ncci_ring_list)
8797 a = plci->adapter;
8798 ncci = plci->ncci_ring_list;
8801 ncci = a->ncci_next[ncci];
8802 ncci_ptr = &(a->ncci[ncci]);
8803 if (!(a->ncci_ch[ncci]
8804 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8806 if (ncci_ptr->data_pending)
8808 if ((a->ncci_state[ncci] == CONNECTED)
8809 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8810 || (plci->send_disc == ncci))
8812 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8813 if ((plci->B2_prot == B2_V120_ASYNC)
8814 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8815 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8817 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8818 plci->NData[1].PLength = data->Length;
8819 if (data->Flags & 0x10)
8820 plci->NData[0].P = v120_break_header;
8821 else
8822 plci->NData[0].P = v120_default_header;
8823 plci->NData[0].PLength = 1 ;
8824 plci->NL.XNum = 2;
8825 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8827 else
8829 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8830 plci->NData[0].PLength = data->Length;
8831 if (data->Flags & 0x10)
8832 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8834 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8835 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8837 else
8838 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8840 plci->NL.X = plci->NData;
8841 plci->NL.ReqCh = a->ncci_ch[ncci];
8842 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8843 plci->data_sent = true;
8844 plci->data_sent_ptr = data->P;
8845 a->request(&plci->NL);
8847 else {
8848 cleanup_ncci_data (plci, ncci);
8851 else if (plci->send_disc == ncci)
8853 /* dprintf("N_DISC"); */
8854 plci->NData[0].PLength = 0;
8855 plci->NL.ReqCh = a->ncci_ch[ncci];
8856 plci->NL.Req = plci->nl_req = N_DISC;
8857 a->request(&plci->NL);
8858 plci->command = _DISCONNECT_B3_R;
8859 plci->send_disc = 0;
8862 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8863 plci->ncci_ring_list = ncci;
8867 void listen_check(DIVA_CAPI_ADAPTER * a)
8869 word i,j;
8870 PLCI * plci;
8871 byte activnotifiedcalls = 0;
8873 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8874 if (!remove_started && !a->adapter_disabled)
8876 for(i=0;i<a->max_plci;i++)
8878 plci = &(a->plci[i]);
8879 if(plci->notifiedcall) activnotifiedcalls++;
8881 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8883 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8884 if((j=get_plci(a))) {
8885 a->listen_active++;
8886 plci = &a->plci[j-1];
8887 plci->State = LISTENING;
8889 add_p(plci,OAD,"\x01\xfd");
8891 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8893 add_p(plci,CAI,"\x01\xc0");
8894 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8895 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8896 add_p(plci,SHIFT|6,NULL);
8897 add_p(plci,SIN,"\x02\x00\x00");
8898 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8899 sig_req(plci,ASSIGN,DSIG_ID);
8900 send_req(plci);
8906 /*------------------------------------------------------------------*/
8907 /* functions for all parameters sent in INDs */
8908 /*------------------------------------------------------------------*/
8910 void IndParse(PLCI * plci, word * parms_id, byte ** parms, byte multiIEsize)
8912 word ploc; /* points to current location within packet */
8913 byte w;
8914 byte wlen;
8915 byte codeset,lock;
8916 byte * in;
8917 word i;
8918 word code;
8919 word mIEindex = 0;
8920 ploc = 0;
8921 codeset = 0;
8922 lock = 0;
8924 in = plci->Sig.RBuffer->P;
8925 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8926 { /* element but parms array is larger */
8927 parms[i] = (byte *)"";
8929 for(i=0; i<multiIEsize; i++)
8931 parms[i] = (byte *)"";
8934 while(ploc<plci->Sig.RBuffer->length-1) {
8936 /* read information element id and length */
8937 w = in[ploc];
8939 if(w & 0x80) {
8940 /* w &=0xf0; removed, cannot detect congestion levels */
8941 /* upper 4 bit masked with w==SHIFT now */
8942 wlen = 0;
8944 else {
8945 wlen = (byte)(in[ploc+1]+1);
8947 /* check if length valid (not exceeding end of packet) */
8948 if((ploc+wlen) > 270) return ;
8949 if(lock & 0x80) lock &=0x7f;
8950 else codeset = lock;
8952 if((w&0xf0)==SHIFT) {
8953 codeset = in[ploc];
8954 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8955 codeset &=7;
8956 lock |=0x80;
8958 else {
8959 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8960 else code = w;
8961 code |= (codeset<<8);
8963 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8965 if(i<parms_id[0]+1) {
8966 if(!multiIEsize) { /* with multiIEs use next field index, */
8967 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8970 parms[mIEindex] = &in[ploc+1];
8971 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8972 if(parms_id[i]==OAD
8973 || parms_id[i]==CONN_NR
8974 || parms_id[i]==CAD) {
8975 if(in[ploc+2] &0x80) {
8976 in[ploc+0] = (byte)(in[ploc+1]+1);
8977 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8978 in[ploc+2] = 0x80;
8979 parms[mIEindex] = &in[ploc];
8982 mIEindex++; /* effects multiIEs only */
8986 ploc +=(wlen+1);
8988 return ;
8991 /*------------------------------------------------------------------*/
8992 /* try to match a cip from received BC and HLC */
8993 /*------------------------------------------------------------------*/
8995 byte ie_compare(byte * ie1, byte * ie2)
8997 word i;
8998 if(!ie1 || ! ie2) return false;
8999 if(!ie1[0]) return false;
9000 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9001 return true;
9004 word find_cip(DIVA_CAPI_ADAPTER * a, byte * bc, byte * hlc)
9006 word i;
9007 word j;
9009 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9011 for(j=16;j<29 &&
9012 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9013 if(j==29) return i;
9014 return j;
9018 static byte AddInfo(byte **add_i,
9019 byte **fty_i,
9020 byte *esc_chi,
9021 byte *facility)
9023 byte i;
9024 byte j;
9025 byte k;
9026 byte flen;
9027 byte len=0;
9028 /* facility is a nested structure */
9029 /* FTY can be more than once */
9031 if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9033 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9036 else
9038 add_i[0] = (byte *)"";
9040 if(!fty_i[0][0])
9042 add_i[3] = (byte *)"";
9044 else
9045 { /* facility array found */
9046 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9048 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9049 len += fty_i[i][0];
9050 len += 2;
9051 flen=fty_i[i][0];
9052 facility[j++]=0x1c; /* copy fac IE */
9053 for(k=0;k<=flen;k++,j++)
9055 facility[j]=fty_i[i][k];
9056 /* dbug(1,dprintf("%x ",facility[j])); */
9059 facility[0] = len;
9060 add_i[3] = facility;
9062 /* dbug(1,dprintf("FacArrLen=%d ",len)); */
9063 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9064 len += 4; /* calculate length of all */
9065 return(len);
9068 /*------------------------------------------------------------------*/
9069 /* voice and codec features */
9070 /*------------------------------------------------------------------*/
9072 void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER * a)
9074 byte voice_chi[] = "\x02\x18\x01";
9075 byte channel;
9077 channel = chi[chi[0]]&0x3;
9078 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9079 voice_chi[2] = (channel) ? channel : 1;
9080 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9081 add_p(plci,ESC,voice_chi); /* Channel */
9082 sig_req(plci,TEL_CTRL,0);
9083 send_req(plci);
9084 if(a->AdvSignalPLCI)
9086 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9090 void VoiceChannelOff(PLCI *plci)
9092 dbug(1,dprintf("ExtDevOFF"));
9093 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9094 sig_req(plci,TEL_CTRL,0);
9095 send_req(plci);
9096 if(plci->adapter->AdvSignalPLCI)
9098 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9103 word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte hook_listen)
9105 word j;
9106 PLCI *splci;
9108 /* check if hardware supports handset with hook states (adv.codec) */
9109 /* or if just a on board codec is supported */
9110 /* the advanced codec plci is just for internal use */
9112 /* diva Pro with on-board codec: */
9113 if(a->profile.Global_Options & HANDSET)
9115 /* new call, but hook states are already signalled */
9116 if(a->AdvCodecFLAG)
9118 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9120 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9121 return 0x2001; /* codec in use by another application */
9123 if(plci!=0)
9125 a->AdvSignalPLCI = plci;
9126 plci->tel=ADV_VOICE;
9128 return 0; /* adv codec still used */
9130 if((j=get_plci(a)))
9132 splci = &a->plci[j-1];
9133 splci->tel = CODEC_PERMANENT;
9134 /* hook_listen indicates if a facility_req with handset/hook support */
9135 /* was sent. Otherwise if just a call on an external device was made */
9136 /* the codec will be used but the hook info will be discarded (just */
9137 /* the external controller is in use */
9138 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9139 else
9141 splci->State = ADVANCED_VOICE_NOSIG;
9142 if(plci)
9144 plci->spoofed_msg = SPOOFING_REQUIRED;
9146 /* indicate D-ch connect if */
9147 } /* codec is connected OK */
9148 if(plci!=0)
9150 a->AdvSignalPLCI = plci;
9151 plci->tel=ADV_VOICE;
9153 a->AdvSignalAppl = appl;
9154 a->AdvCodecFLAG = true;
9155 a->AdvCodecPLCI = splci;
9156 add_p(splci,CAI,"\x01\x15");
9157 add_p(splci,LLI,"\x01\x00");
9158 add_p(splci,ESC,"\x02\x18\x00");
9159 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9160 splci->internal_command = PERM_COD_ASSIGN;
9161 dbug(1,dprintf("Codec Assign"));
9162 sig_req(splci,ASSIGN,DSIG_ID);
9163 send_req(splci);
9165 else
9167 return 0x2001; /* wrong state, no more plcis */
9170 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9172 if(hook_listen) return 0x300B; /* Facility not supported */
9173 /* no hook with SCOM */
9174 if(plci!=0) plci->tel = CODEC;
9175 dbug(1,dprintf("S/SCOM codec"));
9176 /* first time we use the scom-s codec we must shut down the internal */
9177 /* handset application of the card. This can be done by an assign with */
9178 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9179 if(!a->scom_appl_disable){
9180 if((j=get_plci(a))) {
9181 splci = &a->plci[j-1];
9182 add_p(splci,CAI,"\x01\x80");
9183 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9185 send_req(splci);
9186 a->scom_appl_disable = true;
9188 else{
9189 return 0x2001; /* wrong state, no more plcis */
9193 else return 0x300B; /* Facility not supported */
9195 return 0;
9199 void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9202 dbug(1,dprintf("CodecIdCheck"));
9204 if(a->AdvSignalPLCI == plci)
9206 dbug(1,dprintf("PLCI owns codec"));
9207 VoiceChannelOff(a->AdvCodecPLCI);
9208 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9210 dbug(1,dprintf("remove temp codec PLCI"));
9211 plci_remove(a->AdvCodecPLCI);
9212 a->AdvCodecFLAG = 0;
9213 a->AdvCodecPLCI = NULL;
9214 a->AdvSignalAppl = NULL;
9216 a->AdvSignalPLCI = NULL;
9220 /* -------------------------------------------------------------------
9221 Ask for physical address of card on PCI bus
9222 ------------------------------------------------------------------- */
9223 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9224 IDI_SYNC_REQ * preq) {
9225 a->sdram_bar = 0;
9226 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9227 ENTITY * e = (ENTITY *)preq;
9229 e->user[0] = a->Id - 1;
9230 preq->xdi_sdram_bar.info.bar = 0;
9231 preq->xdi_sdram_bar.Req = 0;
9232 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9234 (*(a->request))(e);
9236 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9237 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9241 /* -------------------------------------------------------------------
9242 Ask XDI about extended features
9243 ------------------------------------------------------------------- */
9244 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9245 IDI_SYNC_REQ * preq;
9246 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9248 char features[4];
9249 preq = (IDI_SYNC_REQ *)&buffer[0];
9251 if (!diva_xdi_extended_features) {
9252 ENTITY * e = (ENTITY *)preq;
9253 diva_xdi_extended_features |= 0x80000000;
9255 e->user[0] = a->Id - 1;
9256 preq->xdi_extended_features.Req = 0;
9257 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9258 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9259 preq->xdi_extended_features.info.features = &features[0];
9261 (*(a->request))(e);
9263 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9265 Check features located in the byte '0'
9267 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9268 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9270 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9271 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9272 dbug(1,dprintf("XDI provides RxDMA"));
9274 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9275 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9277 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9278 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9279 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9285 diva_ask_for_xdi_sdram_bar (a, preq);
9288 /*------------------------------------------------------------------*/
9289 /* automatic law */
9290 /*------------------------------------------------------------------*/
9291 /* called from OS specific part after init time to get the Law */
9292 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9293 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9295 word j;
9296 PLCI *splci;
9298 if(a->automatic_law) {
9299 return;
9301 if((j=get_plci(a))) {
9302 diva_get_extended_adapter_features (a);
9303 splci = &a->plci[j-1];
9304 a->automatic_lawPLCI = splci;
9305 a->automatic_law = 1;
9306 add_p(splci,CAI,"\x01\x80");
9307 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9308 splci->internal_command = USELAW_REQ;
9309 splci->command = 0;
9310 splci->number = 0;
9311 sig_req(splci,ASSIGN,DSIG_ID);
9312 send_req(splci);
9316 /* called from OS specific part if an application sends an Capi20Release */
9317 word CapiRelease(word Id)
9319 word i, j, appls_found;
9320 PLCI *plci;
9321 APPL *this;
9322 DIVA_CAPI_ADAPTER *a;
9324 if (!Id)
9326 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9327 return (_WRONG_APPL_ID);
9330 this = &application[Id-1]; /* get application pointer */
9332 for(i=0,appls_found=0; i<max_appl; i++)
9334 if(application[i].Id) /* an application has been found */
9336 appls_found++;
9340 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9342 a = &adapter[i];
9343 if (a->request)
9345 a->Info_Mask[Id-1] = 0;
9346 a->CIP_Mask[Id-1] = 0;
9347 a->Notification_Mask[Id-1] = 0;
9348 a->codec_listen[Id-1] = NULL;
9349 a->requested_options_table[Id-1] = 0;
9350 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9351 { /* with this application */
9352 plci = &a->plci[j];
9353 if(plci->Id) /* if plci owns no application */
9354 { /* it may be not jet connected */
9355 if(plci->State==INC_CON_PENDING
9356 || plci->State==INC_CON_ALERT)
9358 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9360 clear_c_ind_mask_bit (plci, (word)(Id-1));
9361 if(c_ind_mask_empty (plci))
9363 sig_req(plci,HANGUP,0);
9364 send_req(plci);
9365 plci->State = OUTG_DIS_PENDING;
9369 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9371 clear_c_ind_mask_bit (plci, (word)(Id-1));
9372 if(c_ind_mask_empty (plci))
9374 if(!plci->appl)
9376 plci_remove(plci);
9377 plci->State = IDLE;
9381 if(plci->appl==this)
9383 plci->appl = NULL;
9384 plci_remove(plci);
9385 plci->State = IDLE;
9389 listen_check(a);
9391 if(a->flag_dynamic_l1_down)
9393 if(appls_found==1) /* last application does a capi release */
9395 if((j=get_plci(a)))
9397 plci = &a->plci[j-1];
9398 plci->command = 0;
9399 add_p(plci,OAD,"\x01\xfd");
9400 add_p(plci,CAI,"\x01\x80");
9401 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9402 add_p(plci,SHIFT|6,NULL);
9403 add_p(plci,SIN,"\x02\x00\x00");
9404 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9405 sig_req(plci,ASSIGN,DSIG_ID);
9406 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9407 sig_req(plci,SIG_CTRL,0);
9408 send_req(plci);
9412 if(a->AdvSignalAppl==this)
9414 this->NullCREnable = false;
9415 if (a->AdvCodecPLCI)
9417 plci_remove(a->AdvCodecPLCI);
9418 a->AdvCodecPLCI->tel = 0;
9419 a->AdvCodecPLCI->adv_nl = 0;
9421 a->AdvSignalAppl = NULL;
9422 a->AdvSignalPLCI = NULL;
9423 a->AdvCodecFLAG = 0;
9424 a->AdvCodecPLCI = NULL;
9429 this->Id = 0;
9431 return GOOD;
9434 static word plci_remove_check(PLCI *plci)
9436 if(!plci) return true;
9437 if(!plci->NL.Id && c_ind_mask_empty (plci))
9439 if(plci->Sig.Id == 0xff)
9440 plci->Sig.Id = 0;
9441 if(!plci->Sig.Id)
9443 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9444 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9445 if (plci->Id)
9447 CodecIdCheck(plci->adapter, plci);
9448 clear_b1_config (plci);
9449 ncci_remove (plci, 0, false);
9450 plci_free_msg_in_queue (plci);
9451 channel_flow_control_remove (plci);
9452 plci->Id = 0;
9453 plci->State = IDLE;
9454 plci->channels = 0;
9455 plci->appl = NULL;
9456 plci->notifiedcall = 0;
9458 listen_check(plci->adapter);
9459 return true;
9462 return false;
9466 /*------------------------------------------------------------------*/
9468 static byte plci_nl_busy (PLCI *plci)
9470 /* only applicable for non-multiplexed protocols */
9471 return (plci->nl_req
9472 || (plci->ncci_ring_list
9473 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9474 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9478 /*------------------------------------------------------------------*/
9479 /* DTMF facilities */
9480 /*------------------------------------------------------------------*/
9483 static struct
9485 byte send_mask;
9486 byte listen_mask;
9487 byte character;
9488 byte code;
9489 } dtmf_digit_map[] =
9491 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9492 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9493 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9494 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9495 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9496 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9497 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9498 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9499 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9500 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9501 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9502 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9503 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9504 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9505 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9506 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9507 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9508 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9509 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9510 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9512 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9513 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9514 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9515 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9516 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9517 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9518 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9519 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9520 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9521 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9522 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9523 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9524 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9525 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9526 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9527 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9528 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9529 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9530 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9531 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9532 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9533 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9534 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9535 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9536 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9537 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9538 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9539 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9540 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9541 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9542 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9543 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9544 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9545 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9546 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9547 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9548 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9549 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9550 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9551 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9552 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9553 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9554 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9555 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9556 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9557 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9558 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9559 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9560 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9561 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9562 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9563 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9567 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9570 static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9572 word min_digit_duration, min_gap_duration;
9574 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9575 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9576 (char *)(FILE_), __LINE__, enable_mask));
9578 if (enable_mask != 0)
9580 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9581 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9582 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9583 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9584 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9585 plci->NData[0].PLength = 5;
9587 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9588 plci->NData[0].PLength += 2;
9589 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9592 else
9594 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9595 plci->NData[0].PLength = 1;
9597 capidtmf_recv_disable (&(plci->capidtmf_state));
9600 plci->NData[0].P = plci->internal_req_buffer;
9601 plci->NL.X = plci->NData;
9602 plci->NL.ReqCh = 0;
9603 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9604 plci->adapter->request (&plci->NL);
9608 static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9610 word w, i;
9612 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9613 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9614 (char *)(FILE_), __LINE__, digit_count));
9616 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9617 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9618 PUT_WORD (&plci->internal_req_buffer[1], w);
9619 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9620 PUT_WORD (&plci->internal_req_buffer[3], w);
9621 for (i = 0; i < digit_count; i++)
9623 w = 0;
9624 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9625 && (digit_buffer[i] != dtmf_digit_map[w].character))
9627 w++;
9629 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9630 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9632 plci->NData[0].PLength = 5 + digit_count;
9633 plci->NData[0].P = plci->internal_req_buffer;
9634 plci->NL.X = plci->NData;
9635 plci->NL.ReqCh = 0;
9636 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9637 plci->adapter->request (&plci->NL);
9641 static void dtmf_rec_clear_config (PLCI *plci)
9644 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9645 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9646 (char *)(FILE_), __LINE__));
9648 plci->dtmf_rec_active = 0;
9649 plci->dtmf_rec_pulse_ms = 0;
9650 plci->dtmf_rec_pause_ms = 0;
9652 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9657 static void dtmf_send_clear_config (PLCI *plci)
9660 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9661 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9662 (char *)(FILE_), __LINE__));
9664 plci->dtmf_send_requests = 0;
9665 plci->dtmf_send_pulse_ms = 0;
9666 plci->dtmf_send_pause_ms = 0;
9670 static void dtmf_prepare_switch (dword Id, PLCI *plci)
9673 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9674 UnMapId (Id), (char *)(FILE_), __LINE__));
9676 while (plci->dtmf_send_requests != 0)
9677 dtmf_confirmation (Id, plci);
9681 static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9684 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9685 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9687 return (GOOD);
9691 static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9693 word Info;
9695 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9696 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9698 Info = GOOD;
9699 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9701 switch (plci->adjust_b_state)
9703 case ADJUST_B_RESTORE_DTMF_1:
9704 plci->internal_command = plci->adjust_b_command;
9705 if (plci_nl_busy (plci))
9707 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9708 break;
9710 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9711 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9712 break;
9713 case ADJUST_B_RESTORE_DTMF_2:
9714 if ((Rc != OK) && (Rc != OK_FC))
9716 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9717 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9718 Info = _WRONG_STATE;
9719 break;
9721 break;
9724 return (Info);
9728 static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9730 word internal_command, Info;
9731 byte mask;
9732 byte result[4];
9734 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9735 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9736 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9737 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9739 Info = GOOD;
9740 result[0] = 2;
9741 PUT_WORD (&result[1], DTMF_SUCCESS);
9742 internal_command = plci->internal_command;
9743 plci->internal_command = 0;
9744 mask = 0x01;
9745 switch (plci->dtmf_cmd)
9748 case DTMF_LISTEN_TONE_START:
9749 mask <<= 1;
9750 case DTMF_LISTEN_MF_START:
9751 mask <<= 1;
9753 case DTMF_LISTEN_START:
9754 switch (internal_command)
9756 default:
9757 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9758 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9759 case DTMF_COMMAND_1:
9760 if (adjust_b_process (Id, plci, Rc) != GOOD)
9762 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9763 UnMapId (Id), (char *)(FILE_), __LINE__));
9764 Info = _FACILITY_NOT_SUPPORTED;
9765 break;
9767 if (plci->internal_command)
9768 return;
9769 case DTMF_COMMAND_2:
9770 if (plci_nl_busy (plci))
9772 plci->internal_command = DTMF_COMMAND_2;
9773 return;
9775 plci->internal_command = DTMF_COMMAND_3;
9776 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9777 return;
9778 case DTMF_COMMAND_3:
9779 if ((Rc != OK) && (Rc != OK_FC))
9781 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9782 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9783 Info = _FACILITY_NOT_SUPPORTED;
9784 break;
9787 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9789 plci->dtmf_rec_active |= mask;
9790 break;
9792 break;
9795 case DTMF_LISTEN_TONE_STOP:
9796 mask <<= 1;
9797 case DTMF_LISTEN_MF_STOP:
9798 mask <<= 1;
9800 case DTMF_LISTEN_STOP:
9801 switch (internal_command)
9803 default:
9804 plci->dtmf_rec_active &= ~mask;
9805 if (plci->dtmf_rec_active)
9806 break;
9808 case DTMF_COMMAND_1:
9809 if (plci->dtmf_rec_active)
9811 if (plci_nl_busy (plci))
9813 plci->internal_command = DTMF_COMMAND_1;
9814 return;
9816 plci->dtmf_rec_active &= ~mask;
9817 plci->internal_command = DTMF_COMMAND_2;
9818 dtmf_enable_receiver (plci, false);
9819 return;
9821 Rc = OK;
9822 case DTMF_COMMAND_2:
9823 if ((Rc != OK) && (Rc != OK_FC))
9825 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9826 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9827 Info = _FACILITY_NOT_SUPPORTED;
9828 break;
9831 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9832 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9833 case DTMF_COMMAND_3:
9834 if (adjust_b_process (Id, plci, Rc) != GOOD)
9836 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9837 UnMapId (Id), (char *)(FILE_), __LINE__));
9838 Info = _FACILITY_NOT_SUPPORTED;
9839 break;
9841 if (plci->internal_command)
9842 return;
9843 break;
9845 break;
9848 case DTMF_SEND_TONE:
9849 mask <<= 1;
9850 case DTMF_SEND_MF:
9851 mask <<= 1;
9853 case DTMF_DIGITS_SEND:
9854 switch (internal_command)
9856 default:
9857 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9858 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9859 DTMF_COMMAND_1);
9860 case DTMF_COMMAND_1:
9861 if (adjust_b_process (Id, plci, Rc) != GOOD)
9863 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9864 UnMapId (Id), (char *)(FILE_), __LINE__));
9865 Info = _FACILITY_NOT_SUPPORTED;
9866 break;
9868 if (plci->internal_command)
9869 return;
9870 case DTMF_COMMAND_2:
9871 if (plci_nl_busy (plci))
9873 plci->internal_command = DTMF_COMMAND_2;
9874 return;
9876 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9877 plci->internal_command = DTMF_COMMAND_3;
9878 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9879 return;
9880 case DTMF_COMMAND_3:
9881 if ((Rc != OK) && (Rc != OK_FC))
9883 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9884 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9885 if (plci->dtmf_send_requests != 0)
9886 (plci->dtmf_send_requests)--;
9887 Info = _FACILITY_NOT_SUPPORTED;
9888 break;
9890 return;
9892 break;
9894 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9895 "wws", Info, SELECTOR_DTMF, result);
9899 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9901 word Info;
9902 word i, j;
9903 byte mask;
9904 API_PARSE dtmf_parms[5];
9905 byte result[40];
9907 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9908 UnMapId (Id), (char *)(FILE_), __LINE__));
9910 Info = GOOD;
9911 result[0] = 2;
9912 PUT_WORD (&result[1], DTMF_SUCCESS);
9913 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9915 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9916 UnMapId (Id), (char *)(FILE_), __LINE__));
9917 Info = _FACILITY_NOT_SUPPORTED;
9919 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9921 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9922 UnMapId (Id), (char *)(FILE_), __LINE__));
9923 Info = _WRONG_MESSAGE_FORMAT;
9926 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9927 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9929 if (!((a->requested_options_table[appl->Id-1])
9930 & (1L << PRIVATE_DTMF_TONE)))
9932 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9933 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9934 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9936 else
9938 for (i = 0; i < 32; i++)
9939 result[4 + i] = 0;
9940 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9942 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9944 if (dtmf_digit_map[i].listen_mask != 0)
9945 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9948 else
9950 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9952 if (dtmf_digit_map[i].send_mask != 0)
9953 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9956 result[0] = 3 + 32;
9957 result[3] = 32;
9961 else if (plci == NULL)
9963 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9964 UnMapId (Id), (char *)(FILE_), __LINE__));
9965 Info = _WRONG_IDENTIFIER;
9967 else
9969 if (!plci->State
9970 || !plci->NL.Id || plci->nl_remove_id)
9972 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9973 UnMapId (Id), (char *)(FILE_), __LINE__));
9974 Info = _WRONG_STATE;
9976 else
9978 plci->command = 0;
9979 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9980 mask = 0x01;
9981 switch (plci->dtmf_cmd)
9984 case DTMF_LISTEN_TONE_START:
9985 case DTMF_LISTEN_TONE_STOP:
9986 mask <<= 1;
9987 case DTMF_LISTEN_MF_START:
9988 case DTMF_LISTEN_MF_STOP:
9989 mask <<= 1;
9990 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9991 & (1L << PRIVATE_DTMF_TONE)))
9993 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9994 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9995 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9996 break;
9999 case DTMF_LISTEN_START:
10000 case DTMF_LISTEN_STOP:
10001 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10002 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10004 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10005 UnMapId (Id), (char *)(FILE_), __LINE__));
10006 Info = _FACILITY_NOT_SUPPORTED;
10007 break;
10009 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10011 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10013 plci->dtmf_rec_pulse_ms = 0;
10014 plci->dtmf_rec_pause_ms = 0;
10016 else
10018 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10019 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10022 start_internal_command (Id, plci, dtmf_command);
10023 return (false);
10026 case DTMF_SEND_TONE:
10027 mask <<= 1;
10028 case DTMF_SEND_MF:
10029 mask <<= 1;
10030 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10031 & (1L << PRIVATE_DTMF_TONE)))
10033 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10034 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10035 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10036 break;
10039 case DTMF_DIGITS_SEND:
10040 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10042 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10043 UnMapId (Id), (char *)(FILE_), __LINE__));
10044 Info = _WRONG_MESSAGE_FORMAT;
10045 break;
10047 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10049 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10050 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10052 i = 0;
10053 j = 0;
10054 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10056 j = 0;
10057 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10058 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10059 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10061 j++;
10063 i++;
10065 if (j == DTMF_DIGIT_MAP_ENTRIES)
10067 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10068 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10069 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10070 break;
10072 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10074 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10075 UnMapId (Id), (char *)(FILE_), __LINE__));
10076 Info = _WRONG_STATE;
10077 break;
10079 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10080 start_internal_command (Id, plci, dtmf_command);
10081 return (false);
10083 default:
10084 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10085 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10086 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10090 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10091 "wws", Info, SELECTOR_DTMF, result);
10092 return (false);
10096 static void dtmf_confirmation (dword Id, PLCI *plci)
10098 word Info;
10099 word i;
10100 byte result[4];
10102 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10103 UnMapId (Id), (char *)(FILE_), __LINE__));
10105 Info = GOOD;
10106 result[0] = 2;
10107 PUT_WORD (&result[1], DTMF_SUCCESS);
10108 if (plci->dtmf_send_requests != 0)
10110 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10111 "wws", GOOD, SELECTOR_DTMF, result);
10112 (plci->dtmf_send_requests)--;
10113 for (i = 0; i < plci->dtmf_send_requests; i++)
10114 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10119 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10121 word i, j, n;
10123 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10124 UnMapId (Id), (char *)(FILE_), __LINE__));
10126 n = 0;
10127 for (i = 1; i < length; i++)
10129 j = 0;
10130 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10131 && ((msg[i] != dtmf_digit_map[j].code)
10132 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10134 j++;
10136 if (j < DTMF_DIGIT_MAP_ENTRIES)
10139 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10140 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10141 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10143 if (n + 1 == i)
10145 for (i = length; i > n + 1; i--)
10146 msg[i] = msg[i - 1];
10147 length++;
10148 i++;
10150 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10152 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10154 msg[++n] = dtmf_digit_map[j].character;
10157 if (n != 0)
10159 msg[0] = (byte) n;
10160 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10165 /*------------------------------------------------------------------*/
10166 /* DTMF parameters */
10167 /*------------------------------------------------------------------*/
10169 static void dtmf_parameter_write (PLCI *plci)
10171 word i;
10172 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10174 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10175 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10176 (char *)(FILE_), __LINE__));
10178 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10179 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10180 for (i = 0; i < plci->dtmf_parameter_length; i++)
10181 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10182 add_p (plci, FTY, parameter_buffer);
10183 sig_req (plci, TEL_CTRL, 0);
10184 send_req (plci);
10188 static void dtmf_parameter_clear_config (PLCI *plci)
10191 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10192 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10193 (char *)(FILE_), __LINE__));
10195 plci->dtmf_parameter_length = 0;
10199 static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10202 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10203 UnMapId (Id), (char *)(FILE_), __LINE__));
10208 static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10211 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10212 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10214 return (GOOD);
10218 static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10220 word Info;
10222 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10223 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10225 Info = GOOD;
10226 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10227 && (plci->dtmf_parameter_length != 0))
10229 switch (plci->adjust_b_state)
10231 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10232 plci->internal_command = plci->adjust_b_command;
10233 if (plci->sig_req)
10235 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10236 break;
10238 dtmf_parameter_write (plci);
10239 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10240 break;
10241 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10242 if ((Rc != OK) && (Rc != OK_FC))
10244 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10245 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10246 Info = _WRONG_STATE;
10247 break;
10249 break;
10252 return (Info);
10256 /*------------------------------------------------------------------*/
10257 /* Line interconnect facilities */
10258 /*------------------------------------------------------------------*/
10261 LI_CONFIG *li_config_table;
10262 word li_total_channels;
10265 /*------------------------------------------------------------------*/
10266 /* translate a CHI information element to a channel number */
10267 /* returns 0xff - any channel */
10268 /* 0xfe - chi wrong coding */
10269 /* 0xfd - D-channel */
10270 /* 0x00 - no channel */
10271 /* else channel number / PRI: timeslot */
10272 /* if channels is provided we accept more than one channel. */
10273 /*------------------------------------------------------------------*/
10275 static byte chi_to_channel (byte *chi, dword *pchannelmap)
10277 int p;
10278 int i;
10279 dword map;
10280 byte excl;
10281 byte ofs;
10282 byte ch;
10284 if (pchannelmap) *pchannelmap = 0;
10285 if(!chi[0]) return 0xff;
10286 excl = 0;
10288 if(chi[1] & 0x20) {
10289 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10290 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10291 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10292 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10293 if(chi[1] &0x08) excl = 0x40;
10295 /* int. id present */
10296 if(chi[1] &0x40) {
10297 p=i+1;
10298 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10299 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10302 /* coding standard, Number/Map, Channel Type */
10303 p=i+1;
10304 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10305 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10306 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10308 /* Number/Map */
10309 if(chi[p] &0x10) {
10311 /* map */
10312 if((chi[0]-p)==4) ofs = 0;
10313 else if((chi[0]-p)==3) ofs = 1;
10314 else return 0xfe;
10315 ch = 0;
10316 map = 0;
10317 for(i=0; i<4 && p<chi[0]; i++) {
10318 p++;
10319 ch += 8;
10320 map <<= 8;
10321 if(chi[p]) {
10322 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10323 map |= chi[p];
10326 ch += ofs;
10327 map <<= ofs;
10329 else {
10331 /* number */
10332 p=i+1;
10333 ch = chi[p] &0x3f;
10334 if(pchannelmap) {
10335 if((byte)(chi[0]-p)>30) return 0xfe;
10336 map = 0;
10337 for(i=p; i<=chi[0]; i++) {
10338 if ((chi[i] &0x7f) > 31) return 0xfe;
10339 map |= (1L << (chi[i] &0x7f));
10342 else {
10343 if(p!=chi[0]) return 0xfe;
10344 if (ch > 31) return 0xfe;
10345 map = (1L << ch);
10347 if(chi[p] &0x40) return 0xfe;
10349 if (pchannelmap) *pchannelmap = map;
10350 else if (map != ((dword)(1L << ch))) return 0xfe;
10351 return (byte)(excl | ch);
10353 else { /* not PRI */
10354 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10355 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10356 if(chi[1] &0x08) excl = 0x40;
10358 switch(chi[1] |0x98) {
10359 case 0x98: return 0;
10360 case 0x99:
10361 if (pchannelmap) *pchannelmap = 2;
10362 return excl |1;
10363 case 0x9a:
10364 if (pchannelmap) *pchannelmap = 4;
10365 return excl |2;
10366 case 0x9b: return 0xff;
10367 case 0x9c: return 0xfd; /* d-ch */
10368 default: return 0xfe;
10374 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10376 DIVA_CAPI_ADAPTER *a;
10377 PLCI *splci;
10378 byte old_id;
10380 a = plci->adapter;
10381 old_id = plci->li_bchannel_id;
10382 if (a->li_pri)
10384 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10385 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10386 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10387 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10388 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10390 else
10392 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10394 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10395 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10396 plci->li_bchannel_id = bchannel_id & 0x03;
10397 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10399 splci = a->AdvSignalPLCI;
10400 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10402 if ((splci->li_bchannel_id != 0)
10403 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10405 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10407 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10408 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10409 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10410 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10411 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10414 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10415 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10418 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10419 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10421 mixer_clear_config (plci);
10423 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10424 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10425 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10429 static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10431 DIVA_CAPI_ADAPTER *a;
10432 PLCI *splci;
10433 byte ch, old_id;
10435 a = plci->adapter;
10436 old_id = plci->li_bchannel_id;
10437 ch = chi_to_channel (chi, NULL);
10438 if (!(ch & 0x80))
10440 if (a->li_pri)
10442 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10443 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10444 plci->li_bchannel_id = (ch & 0x1f) + 1;
10445 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10446 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10448 else
10450 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10452 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10453 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10454 plci->li_bchannel_id = ch & 0x1f;
10455 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10457 splci = a->AdvSignalPLCI;
10458 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10460 if ((splci->li_bchannel_id != 0)
10461 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10463 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10465 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10466 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10467 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10468 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10469 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10472 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10473 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10477 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10478 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10480 mixer_clear_config (plci);
10482 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10483 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10484 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10488 #define MIXER_MAX_DUMP_CHANNELS 34
10490 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10492 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10493 word n, i, j;
10494 char *p;
10495 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10497 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10498 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10500 for (i = 0; i < li_total_channels; i++)
10502 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10503 if (li_config_table[i].chflags != 0)
10504 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10505 else
10507 for (j = 0; j < li_total_channels; j++)
10509 if (((li_config_table[i].flag_table[j]) != 0)
10510 || ((li_config_table[j].flag_table[i]) != 0))
10512 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10514 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10515 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10517 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10522 for (i = 0; i < li_total_channels; i++)
10524 for (j = 0; j < li_total_channels; j++)
10526 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10527 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10528 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10531 for (n = 0; n < li_total_channels; n++)
10533 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10535 for (i = 0; i < li_total_channels; i++)
10537 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10539 for (j = 0; j < li_total_channels; j++)
10541 li_config_table[i].coef_table[j] |=
10542 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10548 for (i = 0; i < li_total_channels; i++)
10550 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10552 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10553 for (j = 0; j < li_total_channels; j++)
10555 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10556 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10558 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10559 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10562 for (i = 0; i < li_total_channels; i++)
10564 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10566 for (j = 0; j < li_total_channels; j++)
10568 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10569 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10570 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10571 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10572 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10573 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10574 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10575 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10577 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10579 for (j = 0; j < li_total_channels; j++)
10581 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10583 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10584 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10585 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10589 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10591 for (j = 0; j < li_total_channels; j++)
10593 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10594 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10597 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10599 for (j = 0; j < li_total_channels; j++)
10601 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10603 for (n = 0; n < li_total_channels; n++)
10605 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10607 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10608 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10610 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10611 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10612 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10614 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10615 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10623 for (i = 0; i < li_total_channels; i++)
10625 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10627 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10628 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10629 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10630 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10631 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10632 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10633 for (j = 0; j < li_total_channels; j++)
10635 if ((li_config_table[i].flag_table[j] &
10636 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10637 || (li_config_table[j].flag_table[i] &
10638 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10640 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10642 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10643 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10644 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10645 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10647 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10649 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10650 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10654 for (i = 0; i < li_total_channels; i++)
10656 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10658 j = 0;
10659 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10660 j++;
10661 if (j < li_total_channels)
10663 for (j = 0; j < li_total_channels; j++)
10665 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10666 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10667 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10672 n = li_total_channels;
10673 if (n > MIXER_MAX_DUMP_CHANNELS)
10674 n = MIXER_MAX_DUMP_CHANNELS;
10675 p = hex_line;
10676 for (j = 0; j < n; j++)
10678 if ((j & 0x7) == 0)
10679 *(p++) = ' ';
10680 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10681 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10683 *p = '\0';
10684 dbug (1, dprintf ("[%06lx] CURRENT %s",
10685 (dword)(UnMapController (a->Id)), (char *) hex_line));
10686 p = hex_line;
10687 for (j = 0; j < n; j++)
10689 if ((j & 0x7) == 0)
10690 *(p++) = ' ';
10691 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10692 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10694 *p = '\0';
10695 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10696 (dword)(UnMapController (a->Id)), (char *) hex_line));
10697 p = hex_line;
10698 for (j = 0; j < n; j++)
10700 if ((j & 0x7) == 0)
10701 *(p++) = ' ';
10702 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10703 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10705 *p = '\0';
10706 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10707 (dword)(UnMapController (a->Id)), (char *) hex_line));
10708 for (i = 0; i < n; i++)
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[i].flag_table[j] >> 4];
10716 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10718 *p = '\0';
10719 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10720 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10722 for (i = 0; i < n; i++)
10724 p = hex_line;
10725 for (j = 0; j < n; j++)
10727 if ((j & 0x7) == 0)
10728 *(p++) = ' ';
10729 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10730 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10732 *p = '\0';
10733 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10734 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10739 static struct
10741 byte mask;
10742 byte line_flags;
10743 } mixer_write_prog_pri[] =
10745 { LI_COEF_CH_CH, 0 },
10746 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10747 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10748 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10751 static struct
10753 byte from_ch;
10754 byte to_ch;
10755 byte mask;
10756 byte xconnect_override;
10757 } mixer_write_prog_bri[] =
10759 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10760 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10761 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10762 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10763 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10764 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10765 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10766 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10767 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10768 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10769 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10770 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10771 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10772 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10773 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10774 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10775 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10776 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10777 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10778 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10779 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10780 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10781 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10782 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10783 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10784 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10785 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10786 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10787 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10788 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10789 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10790 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10791 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10792 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10793 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10794 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10797 static byte mixer_swapped_index_bri[] =
10799 18, /* B to B */
10800 19, /* Alt B to B */
10801 20, /* PC to B */
10802 21, /* Alt PC to B */
10803 22, /* IC to B */
10804 23, /* Alt IC to B */
10805 24, /* B to PC */
10806 25, /* Alt B to PC */
10807 26, /* PC to PC */
10808 27, /* Alt PC to PC */
10809 28, /* IC to PC */
10810 29, /* Alt IC to PC */
10811 30, /* B to IC */
10812 31, /* Alt B to IC */
10813 32, /* PC to IC */
10814 33, /* Alt PC to IC */
10815 34, /* IC to IC */
10816 35, /* Alt IC to IC */
10817 0, /* Alt B to Alt B */
10818 1, /* B to Alt B */
10819 2, /* Alt PC to Alt B */
10820 3, /* PC to Alt B */
10821 4, /* Alt IC to Alt B */
10822 5, /* IC to Alt B */
10823 6, /* Alt B to Alt PC */
10824 7, /* B to Alt PC */
10825 8, /* Alt PC to Alt PC */
10826 9, /* PC to Alt PC */
10827 10, /* Alt IC to Alt PC */
10828 11, /* IC to Alt PC */
10829 12, /* Alt B to Alt IC */
10830 13, /* B to Alt IC */
10831 14, /* Alt PC to Alt IC */
10832 15, /* PC to Alt IC */
10833 16, /* Alt IC to Alt IC */
10834 17 /* IC to Alt IC */
10837 static struct
10839 byte mask;
10840 byte from_pc;
10841 byte to_pc;
10842 } xconnect_write_prog[] =
10844 { LI_COEF_CH_CH, false, false },
10845 { LI_COEF_CH_PC, false, true },
10846 { LI_COEF_PC_CH, true, false },
10847 { LI_COEF_PC_PC, true, true }
10851 static void xconnect_query_addresses (PLCI *plci)
10853 DIVA_CAPI_ADAPTER *a;
10854 word w, ch;
10855 byte *p;
10857 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10858 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10859 (char *)(FILE_), __LINE__));
10861 a = plci->adapter;
10862 if (a->li_pri && ((plci->li_bchannel_id == 0)
10863 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10865 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10866 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10867 (char *)(FILE_), __LINE__));
10868 return;
10870 p = plci->internal_req_buffer;
10871 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10872 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10873 w = ch;
10874 *(p++) = (byte) w;
10875 *(p++) = (byte)(w >> 8);
10876 w = ch | XCONNECT_CHANNEL_PORT_PC;
10877 *(p++) = (byte) w;
10878 *(p++) = (byte)(w >> 8);
10879 plci->NData[0].P = plci->internal_req_buffer;
10880 plci->NData[0].PLength = p - plci->internal_req_buffer;
10881 plci->NL.X = plci->NData;
10882 plci->NL.ReqCh = 0;
10883 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10884 plci->adapter->request (&plci->NL);
10888 static void xconnect_write_coefs (PLCI *plci, word internal_command)
10891 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10892 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10893 (char *)(FILE_), __LINE__, internal_command));
10895 plci->li_write_command = internal_command;
10896 plci->li_write_channel = 0;
10900 static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10902 DIVA_CAPI_ADAPTER *a;
10903 word w, n, i, j, r, s, to_ch;
10904 dword d;
10905 byte *p;
10906 struct xconnect_transfer_address_s *transfer_address;
10907 byte ch_map[MIXER_CHANNELS_BRI];
10909 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10910 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10912 a = plci->adapter;
10913 if ((plci->li_bchannel_id == 0)
10914 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10916 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10917 UnMapId (Id), (char *)(FILE_), __LINE__));
10918 return (true);
10920 i = a->li_base + (plci->li_bchannel_id - 1);
10921 j = plci->li_write_channel;
10922 p = plci->internal_req_buffer;
10923 if (j != 0)
10925 if ((Rc != OK) && (Rc != OK_FC))
10927 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10928 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10929 return (false);
10932 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10934 r = 0;
10935 s = 0;
10936 if (j < li_total_channels)
10938 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10940 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10941 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10942 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10943 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10945 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10946 while ((j < li_total_channels)
10947 && ((r == 0)
10948 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10949 || (!li_config_table[j].adapter->li_pri
10950 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10951 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10952 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10953 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10954 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10955 || ((li_config_table[j].adapter->li_base != a->li_base)
10956 && !(r & s &
10957 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10958 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10959 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10960 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10962 j++;
10963 if (j < li_total_channels)
10964 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10967 if (j < li_total_channels)
10969 plci->internal_command = plci->li_write_command;
10970 if (plci_nl_busy (plci))
10971 return (true);
10972 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10973 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10976 if (li_config_table[j].adapter->li_base != a->li_base)
10978 r &= s &
10979 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10980 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10981 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10982 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10984 n = 0;
10987 if (r & xconnect_write_prog[n].mask)
10989 if (xconnect_write_prog[n].from_pc)
10990 transfer_address = &(li_config_table[j].send_pc);
10991 else
10992 transfer_address = &(li_config_table[j].send_b);
10993 d = transfer_address->card_address.low;
10994 *(p++) = (byte) d;
10995 *(p++) = (byte)(d >> 8);
10996 *(p++) = (byte)(d >> 16);
10997 *(p++) = (byte)(d >> 24);
10998 d = transfer_address->card_address.high;
10999 *(p++) = (byte) d;
11000 *(p++) = (byte)(d >> 8);
11001 *(p++) = (byte)(d >> 16);
11002 *(p++) = (byte)(d >> 24);
11003 d = transfer_address->offset;
11004 *(p++) = (byte) d;
11005 *(p++) = (byte)(d >> 8);
11006 *(p++) = (byte)(d >> 16);
11007 *(p++) = (byte)(d >> 24);
11008 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11009 *(p++) = (byte) w;
11010 *(p++) = (byte)(w >> 8);
11011 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11012 (li_config_table[i].adapter->u_law ?
11013 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11014 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11015 *(p++) = (byte) w;
11016 *(p++) = (byte) 0;
11017 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11019 n++;
11020 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11021 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11022 if (n == ARRAY_SIZE(xconnect_write_prog))
11026 j++;
11027 if (j < li_total_channels)
11028 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11029 } while ((j < li_total_channels)
11030 && ((r == 0)
11031 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11032 || (!li_config_table[j].adapter->li_pri
11033 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11034 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11035 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11036 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11037 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11038 || ((li_config_table[j].adapter->li_base != a->li_base)
11039 && !(r & s &
11040 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11041 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11042 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11043 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11045 } while ((j < li_total_channels)
11046 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11048 else if (j == li_total_channels)
11050 plci->internal_command = plci->li_write_command;
11051 if (plci_nl_busy (plci))
11052 return (true);
11053 if (a->li_pri)
11055 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11056 w = 0;
11057 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11058 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11059 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11060 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11061 *(p++) = (byte) w;
11062 *(p++) = (byte)(w >> 8);
11064 else
11066 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11067 w = 0;
11068 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11069 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11071 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11073 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11074 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11075 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11076 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11077 *(p++) = (byte) w;
11078 *(p++) = (byte)(w >> 8);
11079 for (j = 0; j < sizeof(ch_map); j += 2)
11081 if (plci->li_bchannel_id == 2)
11083 ch_map[j] = (byte)(j+1);
11084 ch_map[j+1] = (byte) j;
11086 else
11088 ch_map[j] = (byte) j;
11089 ch_map[j+1] = (byte)(j+1);
11092 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11094 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11095 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11096 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11098 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11099 mixer_write_prog_bri[n].xconnect_override :
11100 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11101 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11103 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11104 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11107 else
11109 *p = 0x00;
11110 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11112 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11113 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11114 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11117 p++;
11120 j = li_total_channels + 1;
11123 else
11125 if (j <= li_total_channels)
11127 plci->internal_command = plci->li_write_command;
11128 if (plci_nl_busy (plci))
11129 return (true);
11130 if (j < a->li_base)
11131 j = a->li_base;
11132 if (a->li_pri)
11134 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11135 w = 0;
11136 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11137 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11138 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11139 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11140 *(p++) = (byte) w;
11141 *(p++) = (byte)(w >> 8);
11142 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11144 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11145 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11147 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11148 if (w & mixer_write_prog_pri[n].mask)
11150 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11151 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11153 else
11154 *(p++) = 0x00;
11156 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11157 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11159 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11160 if (w & mixer_write_prog_pri[n].mask)
11162 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11163 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11165 else
11166 *(p++) = 0x00;
11170 else
11172 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11173 w = 0;
11174 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11175 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11177 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11179 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11180 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11181 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11182 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11183 *(p++) = (byte) w;
11184 *(p++) = (byte)(w >> 8);
11185 for (j = 0; j < sizeof(ch_map); j += 2)
11187 if (plci->li_bchannel_id == 2)
11189 ch_map[j] = (byte)(j+1);
11190 ch_map[j+1] = (byte) j;
11192 else
11194 ch_map[j] = (byte) j;
11195 ch_map[j+1] = (byte)(j+1);
11198 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11200 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11201 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11202 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11204 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11205 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11206 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11208 else
11210 *p = 0x00;
11211 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11213 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11214 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11215 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11218 p++;
11221 j = li_total_channels + 1;
11224 plci->li_write_channel = j;
11225 if (p != plci->internal_req_buffer)
11227 plci->NData[0].P = plci->internal_req_buffer;
11228 plci->NData[0].PLength = p - plci->internal_req_buffer;
11229 plci->NL.X = plci->NData;
11230 plci->NL.ReqCh = 0;
11231 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11232 plci->adapter->request (&plci->NL);
11234 return (true);
11238 static void mixer_notify_update (PLCI *plci, byte others)
11240 DIVA_CAPI_ADAPTER *a;
11241 word i, w;
11242 PLCI *notify_plci;
11243 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11245 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11246 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11247 (char *)(FILE_), __LINE__, others));
11249 a = plci->adapter;
11250 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11252 if (others)
11253 plci->li_notify_update = true;
11254 i = 0;
11257 notify_plci = NULL;
11258 if (others)
11260 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11261 i++;
11262 if (i < li_total_channels)
11263 notify_plci = li_config_table[i++].plci;
11265 else
11267 if ((plci->li_bchannel_id != 0)
11268 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11270 notify_plci = plci;
11273 if ((notify_plci != NULL)
11274 && !notify_plci->li_notify_update
11275 && (notify_plci->appl != NULL)
11276 && (notify_plci->State)
11277 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11279 notify_plci->li_notify_update = true;
11280 ((CAPI_MSG *) msg)->header.length = 18;
11281 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11282 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11283 ((CAPI_MSG *) msg)->header.number = 0;
11284 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11285 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11286 ((CAPI_MSG *) msg)->header.ncci = 0;
11287 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11288 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11289 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11290 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11291 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11292 if (w != _QUEUE_FULL)
11294 if (w != 0)
11296 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11297 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11298 (char *)(FILE_), __LINE__,
11299 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11301 notify_plci->li_notify_update = false;
11304 } while (others && (notify_plci != NULL));
11305 if (others)
11306 plci->li_notify_update = false;
11311 static void mixer_clear_config (PLCI *plci)
11313 DIVA_CAPI_ADAPTER *a;
11314 word i, j;
11316 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11317 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11318 (char *)(FILE_), __LINE__));
11320 plci->li_notify_update = false;
11321 plci->li_plci_b_write_pos = 0;
11322 plci->li_plci_b_read_pos = 0;
11323 plci->li_plci_b_req_pos = 0;
11324 a = plci->adapter;
11325 if ((plci->li_bchannel_id != 0)
11326 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11328 i = a->li_base + (plci->li_bchannel_id - 1);
11329 li_config_table[i].curchnl = 0;
11330 li_config_table[i].channel = 0;
11331 li_config_table[i].chflags = 0;
11332 for (j = 0; j < li_total_channels; j++)
11334 li_config_table[j].flag_table[i] = 0;
11335 li_config_table[i].flag_table[j] = 0;
11336 li_config_table[i].coef_table[j] = 0;
11337 li_config_table[j].coef_table[i] = 0;
11339 if (!a->li_pri)
11341 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11342 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11344 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11345 li_config_table[i].curchnl = 0;
11346 li_config_table[i].channel = 0;
11347 li_config_table[i].chflags = 0;
11348 for (j = 0; j < li_total_channels; j++)
11350 li_config_table[i].flag_table[j] = 0;
11351 li_config_table[j].flag_table[i] = 0;
11352 li_config_table[i].coef_table[j] = 0;
11353 li_config_table[j].coef_table[i] = 0;
11355 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11357 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11358 li_config_table[i].curchnl = 0;
11359 li_config_table[i].channel = 0;
11360 li_config_table[i].chflags = 0;
11361 for (j = 0; j < li_total_channels; j++)
11363 li_config_table[i].flag_table[j] = 0;
11364 li_config_table[j].flag_table[i] = 0;
11365 li_config_table[i].coef_table[j] = 0;
11366 li_config_table[j].coef_table[i] = 0;
11375 static void mixer_prepare_switch (dword Id, PLCI *plci)
11378 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11379 UnMapId (Id), (char *)(FILE_), __LINE__));
11383 mixer_indication_coefs_set (Id, plci);
11384 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11388 static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11390 DIVA_CAPI_ADAPTER *a;
11391 word i, j;
11393 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11394 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11396 a = plci->adapter;
11397 if ((plci->li_bchannel_id != 0)
11398 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11400 i = a->li_base + (plci->li_bchannel_id - 1);
11401 for (j = 0; j < li_total_channels; j++)
11403 li_config_table[i].coef_table[j] &= 0xf;
11404 li_config_table[j].coef_table[i] &= 0xf;
11406 if (!a->li_pri)
11407 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11409 return (GOOD);
11413 static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11415 DIVA_CAPI_ADAPTER *a;
11416 word Info;
11418 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11419 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11421 Info = GOOD;
11422 a = plci->adapter;
11423 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11424 && (plci->li_bchannel_id != 0)
11425 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11427 switch (plci->adjust_b_state)
11429 case ADJUST_B_RESTORE_MIXER_1:
11430 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11432 plci->internal_command = plci->adjust_b_command;
11433 if (plci_nl_busy (plci))
11435 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11436 break;
11438 xconnect_query_addresses (plci);
11439 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11440 break;
11442 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11443 Rc = OK;
11444 case ADJUST_B_RESTORE_MIXER_2:
11445 case ADJUST_B_RESTORE_MIXER_3:
11446 case ADJUST_B_RESTORE_MIXER_4:
11447 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11449 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11450 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11451 Info = _WRONG_STATE;
11452 break;
11454 if (Rc == OK)
11456 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11457 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11458 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11459 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11461 else if (Rc == 0)
11463 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11464 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11465 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11466 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11468 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11470 plci->internal_command = plci->adjust_b_command;
11471 break;
11473 case ADJUST_B_RESTORE_MIXER_5:
11474 xconnect_write_coefs (plci, plci->adjust_b_command);
11475 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11476 Rc = OK;
11477 case ADJUST_B_RESTORE_MIXER_6:
11478 if (!xconnect_write_coefs_process (Id, plci, Rc))
11480 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11481 UnMapId (Id), (char *)(FILE_), __LINE__));
11482 Info = _FACILITY_NOT_SUPPORTED;
11483 break;
11485 if (plci->internal_command)
11486 break;
11487 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11488 case ADJUST_B_RESTORE_MIXER_7:
11489 break;
11492 return (Info);
11496 static void mixer_command (dword Id, PLCI *plci, byte Rc)
11498 DIVA_CAPI_ADAPTER *a;
11499 word i, internal_command, Info;
11501 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11502 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11503 plci->li_cmd));
11505 Info = GOOD;
11506 a = plci->adapter;
11507 internal_command = plci->internal_command;
11508 plci->internal_command = 0;
11509 switch (plci->li_cmd)
11511 case LI_REQ_CONNECT:
11512 case LI_REQ_DISCONNECT:
11513 case LI_REQ_SILENT_UPDATE:
11514 switch (internal_command)
11516 default:
11517 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11519 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11520 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11522 case MIXER_COMMAND_1:
11523 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11525 if (adjust_b_process (Id, plci, Rc) != GOOD)
11527 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11528 UnMapId (Id), (char *)(FILE_), __LINE__));
11529 Info = _FACILITY_NOT_SUPPORTED;
11530 break;
11532 if (plci->internal_command)
11533 return;
11535 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11536 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11537 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11538 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11539 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11541 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11543 else
11547 mixer_indication_coefs_set (Id, plci);
11548 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11550 case MIXER_COMMAND_2:
11551 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11552 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11553 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11554 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556 if (!xconnect_write_coefs_process (Id, plci, Rc))
11558 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11559 UnMapId (Id), (char *)(FILE_), __LINE__));
11560 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11564 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11565 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11566 i = (plci->li_plci_b_write_pos == 0) ?
11567 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11568 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11569 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11571 Info = _FACILITY_NOT_SUPPORTED;
11572 break;
11574 if (plci->internal_command)
11575 return;
11577 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11579 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11580 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11582 case MIXER_COMMAND_3:
11583 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11585 if (adjust_b_process (Id, plci, Rc) != GOOD)
11587 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11588 UnMapId (Id), (char *)(FILE_), __LINE__));
11589 Info = _FACILITY_NOT_SUPPORTED;
11590 break;
11592 if (plci->internal_command)
11593 return;
11595 break;
11597 break;
11599 if ((plci->li_bchannel_id == 0)
11600 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11602 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11603 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11605 else
11607 i = a->li_base + (plci->li_bchannel_id - 1);
11608 li_config_table[i].curchnl = plci->li_channel_bits;
11609 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11611 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11612 li_config_table[i].curchnl = plci->li_channel_bits;
11613 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11615 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11616 li_config_table[i].curchnl = plci->li_channel_bits;
11623 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11624 dword plci_b_id, byte connect, dword li_flags)
11626 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11627 PLCI *plci_b;
11628 DIVA_CAPI_ADAPTER *a_b;
11630 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11631 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11632 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11633 if (!a->li_pri && (plci->tel == ADV_VOICE)
11634 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11636 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11637 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11638 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11640 else
11642 ch_a_v = ch_a;
11643 ch_a_s = ch_a;
11645 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11646 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11647 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11649 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11650 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11651 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11653 else
11655 ch_b_v = ch_b;
11656 ch_b_s = ch_b;
11658 if (connect)
11660 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11661 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11662 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11663 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11665 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11666 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11667 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669 if (ch_a_v == ch_b_v)
11671 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11672 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11674 else
11676 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11678 for (i = 0; i < li_total_channels; i++)
11680 if (i != ch_a_v)
11681 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11684 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11686 for (i = 0; i < li_total_channels; i++)
11688 if (i != ch_a_s)
11689 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11692 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11694 for (i = 0; i < li_total_channels; i++)
11696 if (i != ch_a_v)
11697 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11700 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11702 for (i = 0; i < li_total_channels; i++)
11704 if (i != ch_a_s)
11705 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11709 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11711 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11712 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11713 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11714 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11716 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11718 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11719 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11721 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11723 if (li_flags & LI_FLAG_MONITOR_A)
11725 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11726 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11728 if (li_flags & LI_FLAG_MONITOR_B)
11730 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11731 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11733 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11735 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11736 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11738 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11740 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743 if (li_flags & LI_FLAG_MIX_A)
11745 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11746 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11748 if (li_flags & LI_FLAG_MIX_B)
11750 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11751 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11753 if (ch_a_v != ch_a_s)
11755 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11756 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11758 if (ch_b_v != ch_b_s)
11760 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11761 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11766 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11767 dword plci_b_id, byte connect, dword li_flags)
11769 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11770 PLCI *plci_b;
11771 DIVA_CAPI_ADAPTER *a_b;
11773 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11774 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11775 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11776 if (!a->li_pri && (plci->tel == ADV_VOICE)
11777 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11779 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11780 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11781 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11783 else
11785 ch_a_v = ch_a;
11786 ch_a_s = ch_a;
11788 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11789 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11790 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11792 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11793 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11794 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11796 else
11798 ch_b_v = ch_b;
11799 ch_b_s = ch_b;
11801 if (connect)
11803 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11804 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11805 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11806 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11807 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11808 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11810 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11811 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11820 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11821 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11822 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11823 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11825 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11827 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11828 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11830 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11832 if (li_flags & LI2_FLAG_MONITOR_B)
11834 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11835 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11837 if (li_flags & LI2_FLAG_MIX_B)
11839 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11840 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11842 if (li_flags & LI2_FLAG_MONITOR_X)
11843 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11844 if (li_flags & LI2_FLAG_MIX_X)
11845 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11846 if (li_flags & LI2_FLAG_LOOP_B)
11848 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11849 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11850 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11851 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11853 if (li_flags & LI2_FLAG_LOOP_PC)
11854 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11855 if (li_flags & LI2_FLAG_LOOP_X)
11856 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11857 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11858 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11859 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11860 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11861 if (ch_a_v != ch_a_s)
11863 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11864 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11866 if (ch_b_v != ch_b_s)
11868 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11869 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11874 static word li_check_main_plci (dword Id, PLCI *plci)
11876 if (plci == NULL)
11878 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11879 UnMapId (Id), (char *)(FILE_), __LINE__));
11880 return (_WRONG_IDENTIFIER);
11882 if (!plci->State
11883 || !plci->NL.Id || plci->nl_remove_id
11884 || (plci->li_bchannel_id == 0))
11886 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11887 UnMapId (Id), (char *)(FILE_), __LINE__));
11888 return (_WRONG_STATE);
11890 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11891 return (GOOD);
11895 static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11896 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11898 byte ctlr_b;
11899 PLCI *plci_b;
11901 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11902 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11904 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11905 UnMapId (Id), (char *)(FILE_), __LINE__));
11906 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11907 return (NULL);
11909 ctlr_b = 0;
11910 if ((plci_b_id & 0x7f) != 0)
11912 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11913 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11914 ctlr_b = 0;
11916 if ((ctlr_b == 0)
11917 || (((plci_b_id >> 8) & 0xff) == 0)
11918 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11920 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11921 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11922 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11923 return (NULL);
11925 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11926 if (!plci_b->State
11927 || !plci_b->NL.Id || plci_b->nl_remove_id
11928 || (plci_b->li_bchannel_id == 0))
11930 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11931 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11932 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11933 return (NULL);
11935 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11936 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11937 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11938 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11939 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11941 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11942 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11943 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11944 return (NULL);
11946 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11947 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11949 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11950 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11951 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11952 return (NULL);
11954 return (plci_b);
11958 static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11959 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11961 byte ctlr_b;
11962 PLCI *plci_b;
11964 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11965 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11967 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11968 UnMapId (Id), (char *)(FILE_), __LINE__));
11969 PUT_WORD (p_result, _WRONG_STATE);
11970 return (NULL);
11972 ctlr_b = 0;
11973 if ((plci_b_id & 0x7f) != 0)
11975 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11976 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11977 ctlr_b = 0;
11979 if ((ctlr_b == 0)
11980 || (((plci_b_id >> 8) & 0xff) == 0)
11981 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11983 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11984 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11985 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11986 return (NULL);
11988 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11989 if (!plci_b->State
11990 || !plci_b->NL.Id || plci_b->nl_remove_id
11991 || (plci_b->li_bchannel_id == 0)
11992 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11994 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11995 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11996 PUT_WORD (p_result, _WRONG_STATE);
11997 return (NULL);
11999 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12000 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12001 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12002 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12004 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12005 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12006 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12007 return (NULL);
12009 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12010 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12012 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12013 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12014 PUT_WORD (p_result, _WRONG_STATE);
12015 return (NULL);
12017 return (plci_b);
12021 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12023 word Info;
12024 word i;
12025 dword d, li_flags, plci_b_id;
12026 PLCI *plci_b;
12027 API_PARSE li_parms[3];
12028 API_PARSE li_req_parms[3];
12029 API_PARSE li_participant_struct[2];
12030 API_PARSE li_participant_parms[3];
12031 word participant_parms_pos;
12032 byte result_buffer[32];
12033 byte *result;
12034 word result_pos;
12035 word plci_b_write_pos;
12037 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12038 UnMapId (Id), (char *)(FILE_), __LINE__));
12040 Info = GOOD;
12041 result = result_buffer;
12042 result_buffer[0] = 0;
12043 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12045 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12046 UnMapId (Id), (char *)(FILE_), __LINE__));
12047 Info = _FACILITY_NOT_SUPPORTED;
12049 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12051 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12052 UnMapId (Id), (char *)(FILE_), __LINE__));
12053 Info = _WRONG_MESSAGE_FORMAT;
12055 else
12057 result_buffer[0] = 3;
12058 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12059 result_buffer[3] = 0;
12060 switch (GET_WORD (li_parms[0].info))
12062 case LI_GET_SUPPORTED_SERVICES:
12063 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12065 result_buffer[0] = 17;
12066 result_buffer[3] = 14;
12067 PUT_WORD (&result_buffer[4], GOOD);
12068 d = 0;
12069 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12070 d |= LI_CONFERENCING_SUPPORTED;
12071 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12072 d |= LI_MONITORING_SUPPORTED;
12073 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12074 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12075 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12076 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12077 PUT_DWORD (&result_buffer[6], d);
12078 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12080 d = 0;
12081 for (i = 0; i < li_total_channels; i++)
12083 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12084 && (li_config_table[i].adapter->li_pri
12085 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12087 d++;
12091 else
12093 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12095 PUT_DWORD (&result_buffer[10], d / 2);
12096 PUT_DWORD (&result_buffer[14], d);
12098 else
12100 result_buffer[0] = 25;
12101 result_buffer[3] = 22;
12102 PUT_WORD (&result_buffer[4], GOOD);
12103 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12104 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12105 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12106 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12107 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12108 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12109 d |= LI2_PC_LOOPING_SUPPORTED;
12110 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12111 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12112 PUT_DWORD (&result_buffer[6], d);
12113 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12114 PUT_DWORD (&result_buffer[10], d / 2);
12115 PUT_DWORD (&result_buffer[14], d - 1);
12116 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118 d = 0;
12119 for (i = 0; i < li_total_channels; i++)
12121 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12122 && (li_config_table[i].adapter->li_pri
12123 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12125 d++;
12129 PUT_DWORD (&result_buffer[18], d / 2);
12130 PUT_DWORD (&result_buffer[22], d - 1);
12132 break;
12134 case LI_REQ_CONNECT:
12135 if (li_parms[1].length == 8)
12137 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12138 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12140 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12141 UnMapId (Id), (char *)(FILE_), __LINE__));
12142 Info = _WRONG_MESSAGE_FORMAT;
12143 break;
12145 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12146 li_flags = GET_DWORD (li_req_parms[1].info);
12147 Info = li_check_main_plci (Id, plci);
12148 result_buffer[0] = 9;
12149 result_buffer[3] = 6;
12150 PUT_DWORD (&result_buffer[4], plci_b_id);
12151 PUT_WORD (&result_buffer[8], GOOD);
12152 if (Info != GOOD)
12153 break;
12154 result = plci->saved_msg.info;
12155 for (i = 0; i <= result_buffer[0]; i++)
12156 result[i] = result_buffer[i];
12157 plci_b_write_pos = plci->li_plci_b_write_pos;
12158 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12159 if (plci_b == NULL)
12160 break;
12161 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12162 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12163 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12164 plci->li_plci_b_write_pos = plci_b_write_pos;
12166 else
12168 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12169 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12171 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12172 UnMapId (Id), (char *)(FILE_), __LINE__));
12173 Info = _WRONG_MESSAGE_FORMAT;
12174 break;
12176 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12177 Info = li_check_main_plci (Id, plci);
12178 result_buffer[0] = 7;
12179 result_buffer[3] = 4;
12180 PUT_WORD (&result_buffer[4], Info);
12181 result_buffer[6] = 0;
12182 if (Info != GOOD)
12183 break;
12184 result = plci->saved_msg.info;
12185 for (i = 0; i <= result_buffer[0]; i++)
12186 result[i] = result_buffer[i];
12187 plci_b_write_pos = plci->li_plci_b_write_pos;
12188 participant_parms_pos = 0;
12189 result_pos = 7;
12190 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12191 while (participant_parms_pos < li_req_parms[1].length)
12193 result[result_pos] = 6;
12194 result_pos += 7;
12195 PUT_DWORD (&result[result_pos - 6], 0);
12196 PUT_WORD (&result[result_pos - 2], GOOD);
12197 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12198 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12200 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12201 UnMapId (Id), (char *)(FILE_), __LINE__));
12202 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12203 break;
12205 if (api_parse (&li_participant_struct[0].info[1],
12206 li_participant_struct[0].length, "dd", li_participant_parms))
12208 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12209 UnMapId (Id), (char *)(FILE_), __LINE__));
12210 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12211 break;
12213 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12214 li_flags = GET_DWORD (li_participant_parms[1].info);
12215 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12216 if (sizeof(result) - result_pos < 7)
12218 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12219 UnMapId (Id), (char *)(FILE_), __LINE__));
12220 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12221 break;
12223 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12224 if (plci_b != NULL)
12226 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12227 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12228 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12229 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12230 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12232 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12233 (&li_req_parms[1].info[1]));
12235 result[0] = (byte)(result_pos - 1);
12236 result[3] = (byte)(result_pos - 4);
12237 result[6] = (byte)(result_pos - 7);
12238 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12239 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12240 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12242 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12243 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12245 else
12246 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12247 plci->li_plci_b_write_pos = plci_b_write_pos;
12249 mixer_calculate_coefs (a);
12250 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12251 mixer_notify_update (plci, true);
12252 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12253 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12254 plci->command = 0;
12255 plci->li_cmd = GET_WORD (li_parms[0].info);
12256 start_internal_command (Id, plci, mixer_command);
12257 return (false);
12259 case LI_REQ_DISCONNECT:
12260 if (li_parms[1].length == 4)
12262 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12263 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12265 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12266 UnMapId (Id), (char *)(FILE_), __LINE__));
12267 Info = _WRONG_MESSAGE_FORMAT;
12268 break;
12270 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12271 Info = li_check_main_plci (Id, plci);
12272 result_buffer[0] = 9;
12273 result_buffer[3] = 6;
12274 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12275 PUT_WORD (&result_buffer[8], GOOD);
12276 if (Info != GOOD)
12277 break;
12278 result = plci->saved_msg.info;
12279 for (i = 0; i <= result_buffer[0]; i++)
12280 result[i] = result_buffer[i];
12281 plci_b_write_pos = plci->li_plci_b_write_pos;
12282 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12283 if (plci_b == NULL)
12284 break;
12285 li_update_connect (Id, a, plci, plci_b_id, false, 0);
12286 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12287 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12288 plci->li_plci_b_write_pos = plci_b_write_pos;
12290 else
12292 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12293 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12295 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12296 UnMapId (Id), (char *)(FILE_), __LINE__));
12297 Info = _WRONG_MESSAGE_FORMAT;
12298 break;
12300 Info = li_check_main_plci (Id, plci);
12301 result_buffer[0] = 7;
12302 result_buffer[3] = 4;
12303 PUT_WORD (&result_buffer[4], Info);
12304 result_buffer[6] = 0;
12305 if (Info != GOOD)
12306 break;
12307 result = plci->saved_msg.info;
12308 for (i = 0; i <= result_buffer[0]; i++)
12309 result[i] = result_buffer[i];
12310 plci_b_write_pos = plci->li_plci_b_write_pos;
12311 participant_parms_pos = 0;
12312 result_pos = 7;
12313 while (participant_parms_pos < li_req_parms[0].length)
12315 result[result_pos] = 6;
12316 result_pos += 7;
12317 PUT_DWORD (&result[result_pos - 6], 0);
12318 PUT_WORD (&result[result_pos - 2], GOOD);
12319 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12320 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12322 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12323 UnMapId (Id), (char *)(FILE_), __LINE__));
12324 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12325 break;
12327 if (api_parse (&li_participant_struct[0].info[1],
12328 li_participant_struct[0].length, "d", li_participant_parms))
12330 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12331 UnMapId (Id), (char *)(FILE_), __LINE__));
12332 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12333 break;
12335 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12336 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12337 if (sizeof(result) - result_pos < 7)
12339 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12340 UnMapId (Id), (char *)(FILE_), __LINE__));
12341 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12342 break;
12344 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12345 if (plci_b != NULL)
12347 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12348 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12349 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12351 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12352 (&li_req_parms[0].info[1]));
12354 result[0] = (byte)(result_pos - 1);
12355 result[3] = (byte)(result_pos - 4);
12356 result[6] = (byte)(result_pos - 7);
12357 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12358 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12359 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12361 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12362 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12364 else
12365 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12366 plci->li_plci_b_write_pos = plci_b_write_pos;
12368 mixer_calculate_coefs (a);
12369 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12370 mixer_notify_update (plci, true);
12371 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12372 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12373 plci->command = 0;
12374 plci->li_cmd = GET_WORD (li_parms[0].info);
12375 start_internal_command (Id, plci, mixer_command);
12376 return (false);
12378 case LI_REQ_SILENT_UPDATE:
12379 if (!plci || !plci->State
12380 || !plci->NL.Id || plci->nl_remove_id
12381 || (plci->li_bchannel_id == 0)
12382 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12384 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12385 UnMapId (Id), (char *)(FILE_), __LINE__));
12386 return (false);
12388 plci_b_write_pos = plci->li_plci_b_write_pos;
12389 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12390 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12392 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12393 UnMapId (Id), (char *)(FILE_), __LINE__));
12394 return (false);
12396 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12397 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12398 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12400 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12401 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12403 else
12404 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12405 plci->li_plci_b_write_pos = plci_b_write_pos;
12406 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12407 plci->command = 0;
12408 plci->li_cmd = GET_WORD (li_parms[0].info);
12409 start_internal_command (Id, plci, mixer_command);
12410 return (false);
12412 default:
12413 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12414 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12415 Info = _FACILITY_NOT_SUPPORTED;
12418 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12419 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12420 return (false);
12424 static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12426 dword d;
12427 DIVA_CAPI_ADAPTER *a;
12428 byte result[12];
12430 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12431 UnMapId (Id), (char *)(FILE_), __LINE__));
12433 a = plci->adapter;
12434 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12438 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12439 if (!(d & LI_PLCI_B_SKIP_FLAG))
12441 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12443 if (d & LI_PLCI_B_DISC_FLAG)
12445 result[0] = 5;
12446 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12447 result[3] = 2;
12448 PUT_WORD (&result[4], _LI_USER_INITIATED);
12450 else
12452 result[0] = 7;
12453 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12454 result[3] = 4;
12455 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12458 else
12460 if (d & LI_PLCI_B_DISC_FLAG)
12462 result[0] = 9;
12463 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12464 result[3] = 6;
12465 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12466 PUT_WORD (&result[8], _LI_USER_INITIATED);
12468 else
12470 result[0] = 7;
12471 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12472 result[3] = 4;
12473 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12476 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12477 "ws", SELECTOR_LINE_INTERCONNECT, result);
12479 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12480 0 : plci->li_plci_b_read_pos + 1;
12481 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12486 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12488 word i, j, ch;
12489 struct xconnect_transfer_address_s s, *p;
12490 DIVA_CAPI_ADAPTER *a;
12492 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12493 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12495 a = plci->adapter;
12496 i = 1;
12497 for (i = 1; i < length; i += 16)
12499 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12500 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12501 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12502 ch = msg[i+12] | (msg[i+13] << 8);
12503 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12504 if (!a->li_pri && (plci->li_bchannel_id == 2))
12505 j = 1 - j;
12506 j += a->li_base;
12507 if (ch & XCONNECT_CHANNEL_PORT_PC)
12508 p = &(li_config_table[j].send_pc);
12509 else
12510 p = &(li_config_table[j].send_b);
12511 p->card_address.low = s.card_address.low;
12512 p->card_address.high = s.card_address.high;
12513 p->offset = s.offset;
12514 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12516 if (plci->internal_command_queue[0]
12517 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12518 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12519 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12521 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12522 if (!plci->internal_command)
12523 next_internal_command (Id, plci);
12525 mixer_notify_update (plci, true);
12529 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12532 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12533 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12538 static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12540 word plci_b_write_pos;
12542 plci_b_write_pos = plci->li_plci_b_write_pos;
12543 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12544 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12546 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12547 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12548 (char *)(FILE_), __LINE__));
12549 return (false);
12551 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12552 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12553 plci->li_plci_b_write_pos = plci_b_write_pos;
12554 return (true);
12558 static void mixer_remove (PLCI *plci)
12560 DIVA_CAPI_ADAPTER *a;
12561 PLCI *notify_plci;
12562 dword plci_b_id;
12563 word i, j;
12565 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12566 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12567 (char *)(FILE_), __LINE__));
12569 a = plci->adapter;
12570 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12571 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12573 if ((plci->li_bchannel_id != 0)
12574 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12576 i = a->li_base + (plci->li_bchannel_id - 1);
12577 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12579 for (j = 0; j < li_total_channels; j++)
12581 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12582 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12584 notify_plci = li_config_table[j].plci;
12585 if ((notify_plci != NULL)
12586 && (notify_plci != plci)
12587 && (notify_plci->appl != NULL)
12588 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12589 && (notify_plci->State)
12590 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12592 mixer_notify_source_removed (notify_plci, plci_b_id);
12596 mixer_clear_config (plci);
12597 mixer_calculate_coefs (a);
12598 mixer_notify_update (plci, true);
12600 li_config_table[i].plci = NULL;
12601 plci->li_bchannel_id = 0;
12607 /*------------------------------------------------------------------*/
12608 /* Echo canceller facilities */
12609 /*------------------------------------------------------------------*/
12612 static void ec_write_parameters (PLCI *plci)
12614 word w;
12615 byte parameter_buffer[6];
12617 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12618 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12619 (char *)(FILE_), __LINE__));
12621 parameter_buffer[0] = 5;
12622 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12623 PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12624 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12625 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12626 PUT_WORD (&parameter_buffer[4], w);
12627 add_p (plci, FTY, parameter_buffer);
12628 sig_req (plci, TEL_CTRL, 0);
12629 send_req (plci);
12633 static void ec_clear_config (PLCI *plci)
12636 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12637 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12638 (char *)(FILE_), __LINE__));
12640 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12641 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12642 plci->ec_tail_length = 0;
12646 static void ec_prepare_switch (dword Id, PLCI *plci)
12649 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12650 UnMapId (Id), (char *)(FILE_), __LINE__));
12655 static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12658 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12659 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12661 return (GOOD);
12665 static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12667 word Info;
12669 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12670 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672 Info = GOOD;
12673 if (plci->B1_facilities & B1_FACILITY_EC)
12675 switch (plci->adjust_b_state)
12677 case ADJUST_B_RESTORE_EC_1:
12678 plci->internal_command = plci->adjust_b_command;
12679 if (plci->sig_req)
12681 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12682 break;
12684 ec_write_parameters (plci);
12685 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12686 break;
12687 case ADJUST_B_RESTORE_EC_2:
12688 if ((Rc != OK) && (Rc != OK_FC))
12690 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12691 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12692 Info = _WRONG_STATE;
12693 break;
12695 break;
12698 return (Info);
12702 static void ec_command (dword Id, PLCI *plci, byte Rc)
12704 word internal_command, Info;
12705 byte result[8];
12707 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12708 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12709 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12711 Info = GOOD;
12712 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12714 result[0] = 2;
12715 PUT_WORD (&result[1], EC_SUCCESS);
12717 else
12719 result[0] = 5;
12720 PUT_WORD (&result[1], plci->ec_cmd);
12721 result[3] = 2;
12722 PUT_WORD (&result[4], GOOD);
12724 internal_command = plci->internal_command;
12725 plci->internal_command = 0;
12726 switch (plci->ec_cmd)
12728 case EC_ENABLE_OPERATION:
12729 case EC_FREEZE_COEFFICIENTS:
12730 case EC_RESUME_COEFFICIENT_UPDATE:
12731 case EC_RESET_COEFFICIENTS:
12732 switch (internal_command)
12734 default:
12735 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12736 B1_FACILITY_EC), EC_COMMAND_1);
12737 case EC_COMMAND_1:
12738 if (adjust_b_process (Id, plci, Rc) != GOOD)
12740 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12741 UnMapId (Id), (char *)(FILE_), __LINE__));
12742 Info = _FACILITY_NOT_SUPPORTED;
12743 break;
12745 if (plci->internal_command)
12746 return;
12747 case EC_COMMAND_2:
12748 if (plci->sig_req)
12750 plci->internal_command = EC_COMMAND_2;
12751 return;
12753 plci->internal_command = EC_COMMAND_3;
12754 ec_write_parameters (plci);
12755 return;
12756 case EC_COMMAND_3:
12757 if ((Rc != OK) && (Rc != OK_FC))
12759 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12760 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12761 Info = _FACILITY_NOT_SUPPORTED;
12762 break;
12764 break;
12766 break;
12768 case EC_DISABLE_OPERATION:
12769 switch (internal_command)
12771 default:
12772 case EC_COMMAND_1:
12773 if (plci->B1_facilities & B1_FACILITY_EC)
12775 if (plci->sig_req)
12777 plci->internal_command = EC_COMMAND_1;
12778 return;
12780 plci->internal_command = EC_COMMAND_2;
12781 ec_write_parameters (plci);
12782 return;
12784 Rc = OK;
12785 case EC_COMMAND_2:
12786 if ((Rc != OK) && (Rc != OK_FC))
12788 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12789 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12790 Info = _FACILITY_NOT_SUPPORTED;
12791 break;
12793 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12794 ~B1_FACILITY_EC), EC_COMMAND_3);
12795 case EC_COMMAND_3:
12796 if (adjust_b_process (Id, plci, Rc) != GOOD)
12798 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12799 UnMapId (Id), (char *)(FILE_), __LINE__));
12800 Info = _FACILITY_NOT_SUPPORTED;
12801 break;
12803 if (plci->internal_command)
12804 return;
12805 break;
12807 break;
12809 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12810 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12811 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12815 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12817 word Info;
12818 word opt;
12819 API_PARSE ec_parms[3];
12820 byte result[16];
12822 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12823 UnMapId (Id), (char *)(FILE_), __LINE__));
12825 Info = GOOD;
12826 result[0] = 0;
12827 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12829 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12830 UnMapId (Id), (char *)(FILE_), __LINE__));
12831 Info = _FACILITY_NOT_SUPPORTED;
12833 else
12835 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12837 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12839 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12840 UnMapId (Id), (char *)(FILE_), __LINE__));
12841 Info = _WRONG_MESSAGE_FORMAT;
12843 else
12845 if (plci == NULL)
12847 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12848 UnMapId (Id), (char *)(FILE_), __LINE__));
12849 Info = _WRONG_IDENTIFIER;
12851 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12853 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12854 UnMapId (Id), (char *)(FILE_), __LINE__));
12855 Info = _WRONG_STATE;
12857 else
12859 plci->command = 0;
12860 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12861 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12862 result[0] = 2;
12863 PUT_WORD (&result[1], EC_SUCCESS);
12864 if (msg[1].length >= 4)
12866 opt = GET_WORD (&ec_parms[0].info[2]);
12867 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12868 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12869 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12870 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12871 if (opt & EC_DETECT_DISABLE_TONE)
12872 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12873 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12874 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12875 if (msg[1].length >= 6)
12877 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12880 switch (plci->ec_cmd)
12882 case EC_ENABLE_OPERATION:
12883 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12884 start_internal_command (Id, plci, ec_command);
12885 return (false);
12887 case EC_DISABLE_OPERATION:
12888 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12889 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12890 LEC_RESET_COEFFICIENTS;
12891 start_internal_command (Id, plci, ec_command);
12892 return (false);
12894 case EC_FREEZE_COEFFICIENTS:
12895 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12896 start_internal_command (Id, plci, ec_command);
12897 return (false);
12899 case EC_RESUME_COEFFICIENT_UPDATE:
12900 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12901 start_internal_command (Id, plci, ec_command);
12902 return (false);
12904 case EC_RESET_COEFFICIENTS:
12905 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12906 start_internal_command (Id, plci, ec_command);
12907 return (false);
12909 default:
12910 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12911 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12912 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12917 else
12919 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12921 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12922 UnMapId (Id), (char *)(FILE_), __LINE__));
12923 Info = _WRONG_MESSAGE_FORMAT;
12925 else
12927 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12929 result[0] = 11;
12930 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12931 result[3] = 8;
12932 PUT_WORD (&result[4], GOOD);
12933 PUT_WORD (&result[6], 0x0007);
12934 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12935 PUT_WORD (&result[10], 0);
12937 else if (plci == NULL)
12939 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12940 UnMapId (Id), (char *)(FILE_), __LINE__));
12941 Info = _WRONG_IDENTIFIER;
12943 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12945 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12946 UnMapId (Id), (char *)(FILE_), __LINE__));
12947 Info = _WRONG_STATE;
12949 else
12951 plci->command = 0;
12952 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12953 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12954 result[0] = 5;
12955 PUT_WORD (&result[1], plci->ec_cmd);
12956 result[3] = 2;
12957 PUT_WORD (&result[4], GOOD);
12958 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12959 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12960 plci->ec_tail_length = 0;
12961 if (ec_parms[1].length >= 2)
12963 opt = GET_WORD (&ec_parms[1].info[1]);
12964 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12965 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12966 if (opt & EC_DETECT_DISABLE_TONE)
12967 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12968 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12969 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12970 if (ec_parms[1].length >= 4)
12972 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12975 switch (plci->ec_cmd)
12977 case EC_ENABLE_OPERATION:
12978 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12979 start_internal_command (Id, plci, ec_command);
12980 return (false);
12982 case EC_DISABLE_OPERATION:
12983 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12984 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12985 LEC_RESET_COEFFICIENTS;
12986 start_internal_command (Id, plci, ec_command);
12987 return (false);
12989 default:
12990 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12991 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12992 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12998 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12999 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13000 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13001 return (false);
13005 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13007 byte result[8];
13009 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13010 UnMapId (Id), (char *)(FILE_), __LINE__));
13012 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13014 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13016 result[0] = 2;
13017 PUT_WORD (&result[1], 0);
13018 switch (msg[1])
13020 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13021 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13022 break;
13023 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13024 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13025 break;
13026 case LEC_DISABLE_RELEASED:
13027 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13028 break;
13031 else
13033 result[0] = 5;
13034 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13035 result[3] = 2;
13036 PUT_WORD (&result[4], 0);
13037 switch (msg[1])
13039 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13040 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13041 break;
13042 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13043 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13044 break;
13045 case LEC_DISABLE_RELEASED:
13046 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13047 break;
13050 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13051 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13057 /*------------------------------------------------------------------*/
13058 /* Advanced voice */
13059 /*------------------------------------------------------------------*/
13061 static void adv_voice_write_coefs (PLCI *plci, word write_command)
13063 DIVA_CAPI_ADAPTER *a;
13064 word i;
13065 byte *p;
13067 word w, n, j, k;
13068 byte ch_map[MIXER_CHANNELS_BRI];
13070 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13072 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13073 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13074 (char *)(FILE_), __LINE__, write_command));
13076 a = plci->adapter;
13077 p = coef_buffer + 1;
13078 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13079 i = 0;
13080 while (i + sizeof(word) <= a->adv_voice_coef_length)
13082 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13083 p += 2;
13084 i += 2;
13086 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13088 PUT_WORD (p, 0x8000);
13089 p += 2;
13090 i += 2;
13093 if (!a->li_pri && (plci->li_bchannel_id == 0))
13095 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13097 plci->li_bchannel_id = 1;
13098 li_config_table[a->li_base].plci = plci;
13099 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13100 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13101 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13103 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13105 plci->li_bchannel_id = 2;
13106 li_config_table[a->li_base + 1].plci = plci;
13107 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13108 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13109 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13112 if (!a->li_pri && (plci->li_bchannel_id != 0)
13113 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13115 i = a->li_base + (plci->li_bchannel_id - 1);
13116 switch (write_command)
13118 case ADV_VOICE_WRITE_ACTIVATION:
13119 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13120 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13121 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13123 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13124 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13126 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13128 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13129 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13130 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13131 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13133 mixer_calculate_coefs (a);
13134 li_config_table[i].curchnl = li_config_table[i].channel;
13135 li_config_table[j].curchnl = li_config_table[j].channel;
13136 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13137 li_config_table[k].curchnl = li_config_table[k].channel;
13138 break;
13140 case ADV_VOICE_WRITE_DEACTIVATION:
13141 for (j = 0; j < li_total_channels; j++)
13143 li_config_table[i].flag_table[j] = 0;
13144 li_config_table[j].flag_table[i] = 0;
13146 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13147 for (j = 0; j < li_total_channels; j++)
13149 li_config_table[k].flag_table[j] = 0;
13150 li_config_table[j].flag_table[k] = 0;
13152 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13154 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13155 for (j = 0; j < li_total_channels; j++)
13157 li_config_table[k].flag_table[j] = 0;
13158 li_config_table[j].flag_table[k] = 0;
13161 mixer_calculate_coefs (a);
13162 break;
13164 if (plci->B1_facilities & B1_FACILITY_MIXER)
13166 w = 0;
13167 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13168 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13169 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13170 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13171 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13172 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13173 *(p++) = (byte) w;
13174 *(p++) = (byte)(w >> 8);
13175 for (j = 0; j < sizeof(ch_map); j += 2)
13177 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13178 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13180 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13182 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13183 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13184 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13186 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13187 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13188 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13190 else
13192 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13193 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13197 else
13199 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13200 *(p++) = a->adv_voice_coef_buffer[i];
13203 else
13206 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13207 *(p++) = a->adv_voice_coef_buffer[i];
13209 coef_buffer[0] = (p - coef_buffer) - 1;
13210 add_p (plci, FTY, coef_buffer);
13211 sig_req (plci, TEL_CTRL, 0);
13212 send_req (plci);
13216 static void adv_voice_clear_config (PLCI *plci)
13218 DIVA_CAPI_ADAPTER *a;
13220 word i, j;
13223 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13224 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13225 (char *)(FILE_), __LINE__));
13227 a = plci->adapter;
13228 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13230 a->adv_voice_coef_length = 0;
13232 if (!a->li_pri && (plci->li_bchannel_id != 0)
13233 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13235 i = a->li_base + (plci->li_bchannel_id - 1);
13236 li_config_table[i].curchnl = 0;
13237 li_config_table[i].channel = 0;
13238 li_config_table[i].chflags = 0;
13239 for (j = 0; j < li_total_channels; j++)
13241 li_config_table[i].flag_table[j] = 0;
13242 li_config_table[j].flag_table[i] = 0;
13243 li_config_table[i].coef_table[j] = 0;
13244 li_config_table[j].coef_table[i] = 0;
13246 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13247 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13248 li_config_table[i].curchnl = 0;
13249 li_config_table[i].channel = 0;
13250 li_config_table[i].chflags = 0;
13251 for (j = 0; j < li_total_channels; j++)
13253 li_config_table[i].flag_table[j] = 0;
13254 li_config_table[j].flag_table[i] = 0;
13255 li_config_table[i].coef_table[j] = 0;
13256 li_config_table[j].coef_table[i] = 0;
13258 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13260 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13261 li_config_table[i].curchnl = 0;
13262 li_config_table[i].channel = 0;
13263 li_config_table[i].chflags = 0;
13264 for (j = 0; j < li_total_channels; j++)
13266 li_config_table[i].flag_table[j] = 0;
13267 li_config_table[j].flag_table[i] = 0;
13268 li_config_table[i].coef_table[j] = 0;
13269 li_config_table[j].coef_table[i] = 0;
13278 static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13281 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13282 UnMapId (Id), (char *)(FILE_), __LINE__));
13287 static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13290 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13291 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13293 return (GOOD);
13297 static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13299 DIVA_CAPI_ADAPTER *a;
13300 word Info;
13302 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13303 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13305 Info = GOOD;
13306 a = plci->adapter;
13307 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13308 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13310 switch (plci->adjust_b_state)
13312 case ADJUST_B_RESTORE_VOICE_1:
13313 plci->internal_command = plci->adjust_b_command;
13314 if (plci->sig_req)
13316 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13317 break;
13319 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13320 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13321 break;
13322 case ADJUST_B_RESTORE_VOICE_2:
13323 if ((Rc != OK) && (Rc != OK_FC))
13325 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13326 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13327 Info = _WRONG_STATE;
13328 break;
13330 break;
13333 return (Info);
13339 /*------------------------------------------------------------------*/
13340 /* B1 resource switching */
13341 /*------------------------------------------------------------------*/
13343 static byte b1_facilities_table[] =
13345 0x00, /* 0 No bchannel resources */
13346 0x00, /* 1 Codec (automatic law) */
13347 0x00, /* 2 Codec (A-law) */
13348 0x00, /* 3 Codec (y-law) */
13349 0x00, /* 4 HDLC for X.21 */
13350 0x00, /* 5 HDLC */
13351 0x00, /* 6 External Device 0 */
13352 0x00, /* 7 External Device 1 */
13353 0x00, /* 8 HDLC 56k */
13354 0x00, /* 9 Transparent */
13355 0x00, /* 10 Loopback to network */
13356 0x00, /* 11 Test pattern to net */
13357 0x00, /* 12 Rate adaptation sync */
13358 0x00, /* 13 Rate adaptation async */
13359 0x00, /* 14 R-Interface */
13360 0x00, /* 15 HDLC 128k leased line */
13361 0x00, /* 16 FAX */
13362 0x00, /* 17 Modem async */
13363 0x00, /* 18 Modem sync HDLC */
13364 0x00, /* 19 V.110 async HDLC */
13365 0x12, /* 20 Adv voice (Trans,mixer) */
13366 0x00, /* 21 Codec connected to IC */
13367 0x0c, /* 22 Trans,DTMF */
13368 0x1e, /* 23 Trans,DTMF+mixer */
13369 0x1f, /* 24 Trans,DTMF+mixer+local */
13370 0x13, /* 25 Trans,mixer+local */
13371 0x12, /* 26 HDLC,mixer */
13372 0x12, /* 27 HDLC 56k,mixer */
13373 0x2c, /* 28 Trans,LEC+DTMF */
13374 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13375 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13376 0x2c, /* 31 RTP,LEC+DTMF */
13377 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13378 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13379 0x00, /* 34 Signaling task */
13380 0x00, /* 35 PIAFS */
13381 0x0c, /* 36 Trans,DTMF+TONE */
13382 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13383 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13387 static word get_b1_facilities (PLCI * plci, byte b1_resource)
13389 word b1_facilities;
13391 b1_facilities = b1_facilities_table[b1_resource];
13392 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13395 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13396 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13399 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13400 b1_facilities |= B1_FACILITY_DTMFX;
13401 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13402 b1_facilities |= B1_FACILITY_DTMFR;
13405 if ((b1_resource == 17) || (b1_resource == 18))
13407 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13408 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13411 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13412 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13413 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13415 return (b1_facilities);
13419 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13421 byte b;
13423 switch (b1_resource)
13425 case 5:
13426 case 26:
13427 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13428 b = 26;
13429 else
13430 b = 5;
13431 break;
13433 case 8:
13434 case 27:
13435 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13436 b = 27;
13437 else
13438 b = 8;
13439 break;
13441 case 9:
13442 case 20:
13443 case 22:
13444 case 23:
13445 case 24:
13446 case 25:
13447 case 28:
13448 case 29:
13449 case 30:
13450 case 36:
13451 case 37:
13452 case 38:
13453 if (b1_facilities & B1_FACILITY_EC)
13455 if (b1_facilities & B1_FACILITY_LOCAL)
13456 b = 30;
13457 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13458 b = 29;
13459 else
13460 b = 28;
13463 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13464 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13465 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13467 if (b1_facilities & B1_FACILITY_LOCAL)
13468 b = 38;
13469 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13470 b = 37;
13471 else
13472 b = 36;
13475 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13476 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13477 || ((b1_facilities & B1_FACILITY_DTMFR)
13478 && ((b1_facilities & B1_FACILITY_MIXER)
13479 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13480 || ((b1_facilities & B1_FACILITY_DTMFX)
13481 && ((b1_facilities & B1_FACILITY_MIXER)
13482 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13484 if (b1_facilities & B1_FACILITY_LOCAL)
13485 b = 24;
13486 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13487 b = 23;
13488 else
13489 b = 22;
13491 else
13493 if (b1_facilities & B1_FACILITY_LOCAL)
13494 b = 25;
13495 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13496 b = 20;
13497 else
13498 b = 9;
13500 break;
13502 case 31:
13503 case 32:
13504 case 33:
13505 if (b1_facilities & B1_FACILITY_LOCAL)
13506 b = 33;
13507 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13508 b = 32;
13509 else
13510 b = 31;
13511 break;
13513 default:
13514 b = b1_resource;
13516 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13517 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13518 (char *)(FILE_), __LINE__,
13519 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13520 return (b);
13524 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13526 word removed_facilities;
13528 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13529 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13530 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13531 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13533 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13534 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13536 if (removed_facilities & B1_FACILITY_EC)
13537 ec_clear_config (plci);
13540 if (removed_facilities & B1_FACILITY_DTMFR)
13542 dtmf_rec_clear_config (plci);
13543 dtmf_parameter_clear_config (plci);
13545 if (removed_facilities & B1_FACILITY_DTMFX)
13546 dtmf_send_clear_config (plci);
13549 if (removed_facilities & B1_FACILITY_MIXER)
13550 mixer_clear_config (plci);
13552 if (removed_facilities & B1_FACILITY_VOICE)
13553 adv_voice_clear_config (plci);
13554 plci->B1_facilities = new_b1_facilities;
13558 static void adjust_b_clear (PLCI *plci)
13561 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13562 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13563 (char *)(FILE_), __LINE__));
13565 plci->adjust_b_restore = false;
13569 static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13571 word Info;
13572 byte b1_resource;
13573 NCCI * ncci_ptr;
13574 API_PARSE bp[2];
13576 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13577 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13579 Info = GOOD;
13580 switch (plci->adjust_b_state)
13582 case ADJUST_B_START:
13583 if ((plci->adjust_b_parms_msg == NULL)
13584 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13585 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13586 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13588 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13589 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13590 if (b1_resource == plci->B1_resource)
13592 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13593 break;
13595 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13597 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13598 UnMapId (Id), (char *)(FILE_), __LINE__,
13599 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13600 Info = _WRONG_STATE;
13601 break;
13604 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13607 mixer_prepare_switch (Id, plci);
13610 dtmf_prepare_switch (Id, plci);
13611 dtmf_parameter_prepare_switch (Id, plci);
13614 ec_prepare_switch (Id, plci);
13616 adv_voice_prepare_switch (Id, plci);
13618 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13619 Rc = OK;
13620 case ADJUST_B_SAVE_MIXER_1:
13621 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13624 Info = mixer_save_config (Id, plci, Rc);
13625 if ((Info != GOOD) || plci->internal_command)
13626 break;
13629 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13630 Rc = OK;
13631 case ADJUST_B_SAVE_DTMF_1:
13632 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13635 Info = dtmf_save_config (Id, plci, Rc);
13636 if ((Info != GOOD) || plci->internal_command)
13637 break;
13640 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13641 case ADJUST_B_REMOVE_L23_1:
13642 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13643 && plci->NL.Id && !plci->nl_remove_id)
13645 plci->internal_command = plci->adjust_b_command;
13646 if (plci->adjust_b_ncci != 0)
13648 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13649 while (ncci_ptr->data_pending)
13651 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13652 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13654 while (ncci_ptr->data_ack_pending)
13655 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13657 nl_req_ncci (plci, REMOVE,
13658 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13659 send_req (plci);
13660 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13661 break;
13663 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13664 Rc = OK;
13665 case ADJUST_B_REMOVE_L23_2:
13666 if ((Rc != OK) && (Rc != OK_FC))
13668 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13669 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13670 Info = _WRONG_STATE;
13671 break;
13673 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13675 if (plci_nl_busy (plci))
13677 plci->internal_command = plci->adjust_b_command;
13678 break;
13681 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13682 Rc = OK;
13683 case ADJUST_B_SAVE_EC_1:
13684 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13687 Info = ec_save_config (Id, plci, Rc);
13688 if ((Info != GOOD) || plci->internal_command)
13689 break;
13692 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13693 Rc = OK;
13694 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13695 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13698 Info = dtmf_parameter_save_config (Id, plci, Rc);
13699 if ((Info != GOOD) || plci->internal_command)
13700 break;
13703 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13704 Rc = OK;
13705 case ADJUST_B_SAVE_VOICE_1:
13706 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708 Info = adv_voice_save_config (Id, plci, Rc);
13709 if ((Info != GOOD) || plci->internal_command)
13710 break;
13712 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13713 case ADJUST_B_SWITCH_L1_1:
13714 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13716 if (plci->sig_req)
13718 plci->internal_command = plci->adjust_b_command;
13719 break;
13721 if (plci->adjust_b_parms_msg != NULL)
13722 api_load_msg (plci->adjust_b_parms_msg, bp);
13723 else
13724 api_load_msg (&plci->B_protocol, bp);
13725 Info = add_b1 (plci, bp,
13726 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13727 plci->adjust_b_facilities);
13728 if (Info != GOOD)
13730 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13731 UnMapId (Id), (char *)(FILE_), __LINE__,
13732 plci->B1_resource, plci->adjust_b_facilities));
13733 break;
13735 plci->internal_command = plci->adjust_b_command;
13736 sig_req (plci, RESOURCES, 0);
13737 send_req (plci);
13738 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13739 break;
13741 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13742 Rc = OK;
13743 case ADJUST_B_SWITCH_L1_2:
13744 if ((Rc != OK) && (Rc != OK_FC))
13746 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13747 UnMapId (Id), (char *)(FILE_), __LINE__,
13748 Rc, plci->B1_resource, plci->adjust_b_facilities));
13749 Info = _WRONG_STATE;
13750 break;
13752 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13753 Rc = OK;
13754 case ADJUST_B_RESTORE_VOICE_1:
13755 case ADJUST_B_RESTORE_VOICE_2:
13756 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13758 Info = adv_voice_restore_config (Id, plci, Rc);
13759 if ((Info != GOOD) || plci->internal_command)
13760 break;
13762 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13763 Rc = OK;
13764 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13765 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13766 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13769 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13770 if ((Info != GOOD) || plci->internal_command)
13771 break;
13774 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13775 Rc = OK;
13776 case ADJUST_B_RESTORE_EC_1:
13777 case ADJUST_B_RESTORE_EC_2:
13778 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13781 Info = ec_restore_config (Id, plci, Rc);
13782 if ((Info != GOOD) || plci->internal_command)
13783 break;
13786 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13787 case ADJUST_B_ASSIGN_L23_1:
13788 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13790 if (plci_nl_busy (plci))
13792 plci->internal_command = plci->adjust_b_command;
13793 break;
13795 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13796 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13797 if (plci->adjust_b_parms_msg != NULL)
13798 api_load_msg (plci->adjust_b_parms_msg, bp);
13799 else
13800 api_load_msg (&plci->B_protocol, bp);
13801 Info = add_b23 (plci, bp);
13802 if (Info != GOOD)
13804 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13805 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13806 break;
13808 plci->internal_command = plci->adjust_b_command;
13809 nl_req_ncci (plci, ASSIGN, 0);
13810 send_req (plci);
13811 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13812 break;
13814 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13815 Rc = ASSIGN_OK;
13816 case ADJUST_B_ASSIGN_L23_2:
13817 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13819 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13820 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13821 Info = _WRONG_STATE;
13822 break;
13824 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13826 if (Rc != ASSIGN_OK)
13828 plci->internal_command = plci->adjust_b_command;
13829 break;
13832 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13834 plci->adjust_b_restore = true;
13835 break;
13837 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13838 case ADJUST_B_CONNECT_1:
13839 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13841 plci->internal_command = plci->adjust_b_command;
13842 if (plci_nl_busy (plci))
13843 break;
13844 nl_req_ncci (plci, N_CONNECT, 0);
13845 send_req (plci);
13846 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13847 break;
13849 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13850 Rc = OK;
13851 case ADJUST_B_CONNECT_2:
13852 case ADJUST_B_CONNECT_3:
13853 case ADJUST_B_CONNECT_4:
13854 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13856 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13857 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13858 Info = _WRONG_STATE;
13859 break;
13861 if (Rc == OK)
13863 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13865 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13866 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13868 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13869 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13870 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13871 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13873 else if (Rc == 0)
13875 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13876 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13877 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13878 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13880 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13882 plci->internal_command = plci->adjust_b_command;
13883 break;
13885 Rc = OK;
13886 case ADJUST_B_RESTORE_DTMF_1:
13887 case ADJUST_B_RESTORE_DTMF_2:
13888 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13891 Info = dtmf_restore_config (Id, plci, Rc);
13892 if ((Info != GOOD) || plci->internal_command)
13893 break;
13896 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13897 Rc = OK;
13898 case ADJUST_B_RESTORE_MIXER_1:
13899 case ADJUST_B_RESTORE_MIXER_2:
13900 case ADJUST_B_RESTORE_MIXER_3:
13901 case ADJUST_B_RESTORE_MIXER_4:
13902 case ADJUST_B_RESTORE_MIXER_5:
13903 case ADJUST_B_RESTORE_MIXER_6:
13904 case ADJUST_B_RESTORE_MIXER_7:
13905 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13908 Info = mixer_restore_config (Id, plci, Rc);
13909 if ((Info != GOOD) || plci->internal_command)
13910 break;
13913 plci->adjust_b_state = ADJUST_B_END;
13914 case ADJUST_B_END:
13915 break;
13917 return (Info);
13921 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13924 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13925 UnMapId (Id), (char *)(FILE_), __LINE__,
13926 plci->B1_resource, b1_facilities));
13928 plci->adjust_b_parms_msg = bp_msg;
13929 plci->adjust_b_facilities = b1_facilities;
13930 plci->adjust_b_command = internal_command;
13931 plci->adjust_b_ncci = (word)(Id >> 16);
13932 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13933 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13934 else
13935 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13936 plci->adjust_b_state = ADJUST_B_START;
13937 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13938 UnMapId (Id), (char *)(FILE_), __LINE__,
13939 plci->B1_resource, b1_facilities));
13943 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13945 word internal_command;
13947 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13948 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13950 internal_command = plci->internal_command;
13951 plci->internal_command = 0;
13952 switch (internal_command)
13954 default:
13955 plci->command = 0;
13956 if (plci->req_in != 0)
13958 plci->internal_command = ADJUST_B_RESTORE_1;
13959 break;
13961 Rc = OK;
13962 case ADJUST_B_RESTORE_1:
13963 if ((Rc != OK) && (Rc != OK_FC))
13965 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13966 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13968 plci->adjust_b_parms_msg = NULL;
13969 plci->adjust_b_facilities = plci->B1_facilities;
13970 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13971 plci->adjust_b_ncci = (word)(Id >> 16);
13972 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13973 plci->adjust_b_state = ADJUST_B_START;
13974 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13975 UnMapId (Id), (char *)(FILE_), __LINE__));
13976 case ADJUST_B_RESTORE_2:
13977 if (adjust_b_process (Id, plci, Rc) != GOOD)
13979 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13980 UnMapId (Id), (char *)(FILE_), __LINE__));
13982 if (plci->internal_command)
13983 break;
13984 break;
13989 static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13991 word Info;
13992 word internal_command;
13994 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13995 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13997 Info = GOOD;
13998 internal_command = plci->internal_command;
13999 plci->internal_command = 0;
14000 switch (internal_command)
14002 default:
14003 plci->command = 0;
14004 plci->adjust_b_parms_msg = NULL;
14005 plci->adjust_b_facilities = plci->B1_facilities;
14006 plci->adjust_b_command = RESET_B3_COMMAND_1;
14007 plci->adjust_b_ncci = (word)(Id >> 16);
14008 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14009 plci->adjust_b_state = ADJUST_B_START;
14010 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14011 UnMapId (Id), (char *)(FILE_), __LINE__));
14012 case RESET_B3_COMMAND_1:
14013 Info = adjust_b_process (Id, plci, Rc);
14014 if (Info != GOOD)
14016 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14017 UnMapId (Id), (char *)(FILE_), __LINE__));
14018 break;
14020 if (plci->internal_command)
14021 return;
14022 break;
14024 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14025 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14029 static void select_b_command (dword Id, PLCI *plci, byte Rc)
14031 word Info;
14032 word internal_command;
14033 byte esc_chi[3];
14035 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14036 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14038 Info = GOOD;
14039 internal_command = plci->internal_command;
14040 plci->internal_command = 0;
14041 switch (internal_command)
14043 default:
14044 plci->command = 0;
14045 plci->adjust_b_parms_msg = &plci->saved_msg;
14046 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14047 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14048 else
14049 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14050 plci->adjust_b_command = SELECT_B_COMMAND_1;
14051 plci->adjust_b_ncci = (word)(Id >> 16);
14052 if (plci->saved_msg.parms[0].length == 0)
14054 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14055 ADJUST_B_MODE_NO_RESOURCE;
14057 else
14059 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14060 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14062 plci->adjust_b_state = ADJUST_B_START;
14063 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14064 UnMapId (Id), (char *)(FILE_), __LINE__));
14065 case SELECT_B_COMMAND_1:
14066 Info = adjust_b_process (Id, plci, Rc);
14067 if (Info != GOOD)
14069 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14070 UnMapId (Id), (char *)(FILE_), __LINE__));
14071 break;
14073 if (plci->internal_command)
14074 return;
14075 if (plci->tel == ADV_VOICE)
14077 esc_chi[0] = 0x02;
14078 esc_chi[1] = 0x18;
14079 esc_chi[2] = plci->b_channel;
14080 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14082 break;
14084 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14088 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14090 word Info;
14091 word internal_command;
14093 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14094 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14096 Info = GOOD;
14097 internal_command = plci->internal_command;
14098 plci->internal_command = 0;
14099 switch (internal_command)
14101 default:
14102 plci->command = 0;
14103 case FAX_CONNECT_ACK_COMMAND_1:
14104 if (plci_nl_busy (plci))
14106 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14107 return;
14109 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14110 plci->NData[0].P = plci->fax_connect_info_buffer;
14111 plci->NData[0].PLength = plci->fax_connect_info_length;
14112 plci->NL.X = plci->NData;
14113 plci->NL.ReqCh = 0;
14114 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14115 plci->adapter->request (&plci->NL);
14116 return;
14117 case FAX_CONNECT_ACK_COMMAND_2:
14118 if ((Rc != OK) && (Rc != OK_FC))
14120 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14121 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14122 break;
14125 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14126 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14128 if (plci->B3_prot == 4)
14129 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14130 else
14131 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14132 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14137 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14139 word Info;
14140 word internal_command;
14142 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14143 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14145 Info = GOOD;
14146 internal_command = plci->internal_command;
14147 plci->internal_command = 0;
14148 switch (internal_command)
14150 default:
14151 plci->command = 0;
14152 case FAX_EDATA_ACK_COMMAND_1:
14153 if (plci_nl_busy (plci))
14155 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14156 return;
14158 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14159 plci->NData[0].P = plci->fax_connect_info_buffer;
14160 plci->NData[0].PLength = plci->fax_edata_ack_length;
14161 plci->NL.X = plci->NData;
14162 plci->NL.ReqCh = 0;
14163 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14164 plci->adapter->request (&plci->NL);
14165 return;
14166 case FAX_EDATA_ACK_COMMAND_2:
14167 if ((Rc != OK) && (Rc != OK_FC))
14169 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14170 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14171 break;
14177 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14179 word Info;
14180 word internal_command;
14182 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14183 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14185 Info = GOOD;
14186 internal_command = plci->internal_command;
14187 plci->internal_command = 0;
14188 switch (internal_command)
14190 default:
14191 plci->command = 0;
14192 case FAX_CONNECT_INFO_COMMAND_1:
14193 if (plci_nl_busy (plci))
14195 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14196 return;
14198 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14199 plci->NData[0].P = plci->fax_connect_info_buffer;
14200 plci->NData[0].PLength = plci->fax_connect_info_length;
14201 plci->NL.X = plci->NData;
14202 plci->NL.ReqCh = 0;
14203 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14204 plci->adapter->request (&plci->NL);
14205 return;
14206 case FAX_CONNECT_INFO_COMMAND_2:
14207 if ((Rc != OK) && (Rc != OK_FC))
14209 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14210 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14211 Info = _WRONG_STATE;
14212 break;
14214 if (plci_nl_busy (plci))
14216 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14217 return;
14219 plci->command = _CONNECT_B3_R;
14220 nl_req_ncci (plci, N_CONNECT, 0);
14221 send_req (plci);
14222 return;
14224 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14228 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14230 word Info;
14231 word internal_command;
14233 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14234 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14236 Info = GOOD;
14237 internal_command = plci->internal_command;
14238 plci->internal_command = 0;
14239 switch (internal_command)
14241 default:
14242 plci->command = 0;
14243 plci->adjust_b_parms_msg = NULL;
14244 plci->adjust_b_facilities = plci->B1_facilities;
14245 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14246 plci->adjust_b_ncci = (word)(Id >> 16);
14247 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14248 plci->adjust_b_state = ADJUST_B_START;
14249 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14250 UnMapId (Id), (char *)(FILE_), __LINE__));
14251 case FAX_ADJUST_B23_COMMAND_1:
14252 Info = adjust_b_process (Id, plci, Rc);
14253 if (Info != GOOD)
14255 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14256 UnMapId (Id), (char *)(FILE_), __LINE__));
14257 break;
14259 if (plci->internal_command)
14260 return;
14261 case FAX_ADJUST_B23_COMMAND_2:
14262 if (plci_nl_busy (plci))
14264 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14265 return;
14267 plci->command = _CONNECT_B3_R;
14268 nl_req_ncci (plci, N_CONNECT, 0);
14269 send_req (plci);
14270 return;
14272 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14276 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14278 word internal_command;
14280 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14281 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14283 internal_command = plci->internal_command;
14284 plci->internal_command = 0;
14285 switch (internal_command)
14287 default:
14288 plci->command = 0;
14289 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14290 return;
14291 case FAX_DISCONNECT_COMMAND_1:
14292 case FAX_DISCONNECT_COMMAND_2:
14293 case FAX_DISCONNECT_COMMAND_3:
14294 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14296 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14297 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14298 break;
14300 if (Rc == OK)
14302 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14303 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14305 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14308 else if (Rc == 0)
14310 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14311 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14313 return;
14319 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14321 word Info;
14322 word internal_command;
14324 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14325 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14327 Info = GOOD;
14328 internal_command = plci->internal_command;
14329 plci->internal_command = 0;
14330 switch (internal_command)
14332 default:
14333 plci->command = 0;
14334 case RTP_CONNECT_B3_REQ_COMMAND_1:
14335 if (plci_nl_busy (plci))
14337 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14338 return;
14340 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14341 nl_req_ncci (plci, N_CONNECT, 0);
14342 send_req (plci);
14343 return;
14344 case RTP_CONNECT_B3_REQ_COMMAND_2:
14345 if ((Rc != OK) && (Rc != OK_FC))
14347 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14348 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14349 Info = _WRONG_STATE;
14350 break;
14352 if (plci_nl_busy (plci))
14354 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14355 return;
14357 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14358 plci->NData[0].PLength = plci->internal_req_buffer[0];
14359 plci->NData[0].P = plci->internal_req_buffer + 1;
14360 plci->NL.X = plci->NData;
14361 plci->NL.ReqCh = 0;
14362 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14363 plci->adapter->request (&plci->NL);
14364 break;
14365 case RTP_CONNECT_B3_REQ_COMMAND_3:
14366 return;
14368 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14372 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14374 word Info;
14375 word internal_command;
14377 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14378 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14380 Info = GOOD;
14381 internal_command = plci->internal_command;
14382 plci->internal_command = 0;
14383 switch (internal_command)
14385 default:
14386 plci->command = 0;
14387 case RTP_CONNECT_B3_RES_COMMAND_1:
14388 if (plci_nl_busy (plci))
14390 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14391 return;
14393 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14394 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14395 send_req (plci);
14396 return;
14397 case RTP_CONNECT_B3_RES_COMMAND_2:
14398 if ((Rc != OK) && (Rc != OK_FC))
14400 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14401 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14402 Info = _WRONG_STATE;
14403 break;
14405 if (plci_nl_busy (plci))
14407 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14408 return;
14410 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14411 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14412 plci->NData[0].PLength = plci->internal_req_buffer[0];
14413 plci->NData[0].P = plci->internal_req_buffer + 1;
14414 plci->NL.X = plci->NData;
14415 plci->NL.ReqCh = 0;
14416 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14417 plci->adapter->request (&plci->NL);
14418 return;
14419 case RTP_CONNECT_B3_RES_COMMAND_3:
14420 return;
14426 static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14428 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14429 word Info;
14430 word internal_command;
14432 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14433 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14435 Info = GOOD;
14436 internal_command = plci->internal_command;
14437 plci->internal_command = 0;
14438 switch (internal_command)
14440 default:
14441 if (!plci->NL.Id)
14442 break;
14443 plci->command = 0;
14444 plci->adjust_b_parms_msg = NULL;
14445 plci->adjust_b_facilities = plci->B1_facilities;
14446 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14447 plci->adjust_b_ncci = (word)(Id >> 16);
14448 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14449 plci->adjust_b_state = ADJUST_B_START;
14450 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14451 UnMapId (Id), (char *)(FILE_), __LINE__));
14452 case HOLD_SAVE_COMMAND_1:
14453 Info = adjust_b_process (Id, plci, Rc);
14454 if (Info != GOOD)
14456 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14457 UnMapId (Id), (char *)(FILE_), __LINE__));
14458 break;
14460 if (plci->internal_command)
14461 return;
14463 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14467 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14469 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14470 word Info;
14471 word internal_command;
14473 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14474 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14476 Info = GOOD;
14477 internal_command = plci->internal_command;
14478 plci->internal_command = 0;
14479 switch (internal_command)
14481 default:
14482 plci->command = 0;
14483 plci->adjust_b_parms_msg = NULL;
14484 plci->adjust_b_facilities = plci->B1_facilities;
14485 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14486 plci->adjust_b_ncci = (word)(Id >> 16);
14487 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14488 plci->adjust_b_state = ADJUST_B_START;
14489 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14490 UnMapId (Id), (char *)(FILE_), __LINE__));
14491 case RETRIEVE_RESTORE_COMMAND_1:
14492 Info = adjust_b_process (Id, plci, Rc);
14493 if (Info != GOOD)
14495 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14496 UnMapId (Id), (char *)(FILE_), __LINE__));
14497 break;
14499 if (plci->internal_command)
14500 return;
14502 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14506 static void init_b1_config (PLCI *plci)
14509 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14510 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14511 (char *)(FILE_), __LINE__));
14513 plci->B1_resource = 0;
14514 plci->B1_facilities = 0;
14516 plci->li_bchannel_id = 0;
14517 mixer_clear_config (plci);
14520 ec_clear_config (plci);
14523 dtmf_rec_clear_config (plci);
14524 dtmf_send_clear_config (plci);
14525 dtmf_parameter_clear_config (plci);
14527 adv_voice_clear_config (plci);
14528 adjust_b_clear (plci);
14532 static void clear_b1_config (PLCI *plci)
14535 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14536 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14537 (char *)(FILE_), __LINE__));
14539 adv_voice_clear_config (plci);
14540 adjust_b_clear (plci);
14542 ec_clear_config (plci);
14545 dtmf_rec_clear_config (plci);
14546 dtmf_send_clear_config (plci);
14547 dtmf_parameter_clear_config (plci);
14550 if ((plci->li_bchannel_id != 0)
14551 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14553 mixer_clear_config (plci);
14554 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14555 plci->li_bchannel_id = 0;
14558 plci->B1_resource = 0;
14559 plci->B1_facilities = 0;
14563 /* -----------------------------------------------------------------
14564 XON protocol local helpers
14565 ----------------------------------------------------------------- */
14566 static void channel_flow_control_remove (PLCI * plci) {
14567 DIVA_CAPI_ADAPTER * a = plci->adapter;
14568 word i;
14569 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14570 if (a->ch_flow_plci[i] == plci->Id) {
14571 a->ch_flow_plci[i] = 0;
14572 a->ch_flow_control[i] = 0;
14577 static void channel_x_on (PLCI * plci, byte ch) {
14578 DIVA_CAPI_ADAPTER * a = plci->adapter;
14579 if (a->ch_flow_control[ch] & N_XON_SENT) {
14580 a->ch_flow_control[ch] &= ~N_XON_SENT;
14584 static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14585 DIVA_CAPI_ADAPTER * a = plci->adapter;
14586 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14587 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14588 a->ch_flow_plci[ch] = plci->Id;
14589 a->ch_flow_control_pending++;
14593 static void channel_request_xon (PLCI * plci, byte ch) {
14594 DIVA_CAPI_ADAPTER * a = plci->adapter;
14596 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14597 a->ch_flow_control[ch] |= N_XON_REQ;
14598 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14599 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14603 static void channel_xmit_extended_xon (PLCI * plci) {
14604 DIVA_CAPI_ADAPTER * a;
14605 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14606 int i, one_requested = 0;
14608 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14609 return;
14612 for (i = 0; i < max_ch; i++) {
14613 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14614 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14615 (plci->Id == a->ch_flow_plci[i])) {
14616 channel_request_xon (plci, (byte)i);
14617 one_requested = 1;
14621 if (one_requested) {
14622 channel_xmit_xon (plci);
14627 Try to xmit next X_ON
14629 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14630 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14631 int i;
14633 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14634 return (0);
14637 if (a->last_flow_control_ch >= max_ch) {
14638 a->last_flow_control_ch = 1;
14640 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14641 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14642 (plci->Id == a->ch_flow_plci[i])) {
14643 a->last_flow_control_ch = i+1;
14644 return (i);
14648 for (i = 1; i < a->last_flow_control_ch; i++) {
14649 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14650 (plci->Id == a->ch_flow_plci[i])) {
14651 a->last_flow_control_ch = i+1;
14652 return (i);
14656 return (0);
14659 static void channel_xmit_xon (PLCI * plci) {
14660 DIVA_CAPI_ADAPTER * a = plci->adapter;
14661 byte ch;
14663 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14664 return;
14666 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14667 return;
14669 a->ch_flow_control[ch] &= ~N_XON_REQ;
14670 a->ch_flow_control[ch] |= N_XON_SENT;
14672 plci->NL.Req = plci->nl_req = (byte)N_XON;
14673 plci->NL.ReqCh = ch;
14674 plci->NL.X = plci->NData;
14675 plci->NL.XNum = 1;
14676 plci->NData[0].P = &plci->RBuffer[0];
14677 plci->NData[0].PLength = 0;
14679 plci->adapter->request(&plci->NL);
14682 static int channel_can_xon (PLCI * plci, byte ch) {
14683 APPL * APPLptr;
14684 DIVA_CAPI_ADAPTER * a;
14685 word NCCIcode;
14686 dword count;
14687 word Num;
14688 word i;
14690 APPLptr = plci->appl;
14691 a = plci->adapter;
14693 if (!APPLptr)
14694 return (0);
14696 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14698 /* count all buffers within the Application pool */
14699 /* belonging to the same NCCI. XON if a first is */
14700 /* used. */
14701 count = 0;
14702 Num = 0xffff;
14703 for(i=0; i<APPLptr->MaxBuffer; i++) {
14704 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14705 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14707 if ((count > 2) || (Num == 0xffff)) {
14708 return (0);
14710 return (1);
14714 /*------------------------------------------------------------------*/
14716 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14718 return 1;
14723 /**********************************************************************************/
14724 /* function groups the listening applications according to the CIP mask and the */
14725 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14726 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14727 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14728 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14729 /* OS specific part (per adapter). */
14730 /**********************************************************************************/
14731 static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14733 word i,j,k,busy,group_found;
14734 dword info_mask_group[MAX_CIP_TYPES];
14735 dword cip_mask_group[MAX_CIP_TYPES];
14736 word appl_number_group_type[MAX_APPL];
14737 PLCI *auxplci;
14739 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14741 if(!a->group_optimization_enabled)
14743 dbug(1,dprintf("No group optimization"));
14744 return;
14747 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14749 for(i=0;i<MAX_CIP_TYPES;i++)
14751 info_mask_group[i] = 0;
14752 cip_mask_group [i] = 0;
14754 for(i=0;i<MAX_APPL;i++)
14756 appl_number_group_type[i] = 0;
14758 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14759 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14760 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14762 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14763 return; /* allow good application unfiltered access */
14766 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14768 if(application[i].Id && a->CIP_Mask[i] )
14770 for(k=0,busy=false; k<a->max_plci; k++)
14772 if(a->plci[k].Id)
14774 auxplci = &a->plci[k];
14775 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14777 busy = true;
14778 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14780 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14782 busy = true;
14783 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14788 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14790 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14791 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14792 appl_number_group_type[i] = MAX_CIP_TYPES;
14793 group_found=true;
14794 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14796 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14797 { /* is group already present ? */
14798 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14799 group_found=true;
14800 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]));
14802 else if(!info_mask_group[j])
14803 { /* establish a new group */
14804 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14805 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14806 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14807 group_found=true;
14808 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]));
14814 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14816 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14818 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14820 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14822 else
14824 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14825 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14827 if(appl_number_group_type[i] == appl_number_group_type[j])
14829 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14830 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14831 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14836 else /* application should not get a call */
14838 clear_group_ind_mask_bit (plci, i);
14846 /* OS notifies the driver about a application Capi_Register */
14847 word CapiRegister(word id)
14849 word i,j,appls_found;
14851 PLCI *plci;
14852 DIVA_CAPI_ADAPTER *a;
14854 for(i=0,appls_found=0; i<max_appl; i++)
14856 if( application[i].Id && (application[i].Id!=id) )
14858 appls_found++; /* an application has been found */
14862 if(appls_found) return true;
14863 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14865 a = &adapter[i];
14866 if(a->request)
14868 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14870 if(!appls_found) /* first application does a capi register */
14872 if((j=get_plci(a))) /* activate L1 of all adapters */
14874 plci = &a->plci[j-1];
14875 plci->command = 0;
14876 add_p(plci,OAD,"\x01\xfd");
14877 add_p(plci,CAI,"\x01\x80");
14878 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14879 add_p(plci,SHIFT|6,NULL);
14880 add_p(plci,SIN,"\x02\x00\x00");
14881 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14882 sig_req(plci,ASSIGN,DSIG_ID);
14883 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14884 sig_req(plci,SIG_CTRL,0);
14885 send_req(plci);
14891 return false;
14894 /*------------------------------------------------------------------*/
14896 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14898 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14900 word i;
14901 /* Format of vswitch_t:
14902 0 byte length
14903 1 byte VSWITCHIE
14904 2 byte VSWITCH_REQ/VSWITCH_IND
14905 3 byte reserved
14906 4 word VSwitchcommand
14907 6 word returnerror
14908 8... Params
14910 if(!plci ||
14911 !plci->appl ||
14912 !plci->State ||
14913 plci->Sig.Ind==NCR_FACILITY
14915 return;
14917 for(i=0;i<MAX_MULTI_IE;i++)
14919 if(!parms[i][0]) continue;
14920 if(parms[i][0]<7)
14922 parms[i][0]=0; /* kill it */
14923 continue;
14925 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14926 switch(parms[i][4])
14928 case VSJOIN:
14929 if(!plci->relatedPTYPLCI ||
14930 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14931 { /* Error */
14932 break;
14934 /* remember all necessary informations */
14935 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14937 break;
14939 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14940 { /* first indication after ECT-Request on Consultation Call */
14941 plci->vswitchstate=parms[i][9];
14942 parms[i][9]=2; /* State */
14943 /* now ask first Call to join */
14945 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14946 { /* Answer of VSWITCH_REQ from first Call */
14947 plci->vswitchstate=parms[i][9];
14948 /* tell consultation call to join
14949 and the protocol capabilities of the first call */
14951 else
14952 { /* Error */
14953 break;
14955 plci->vsprot=parms[i][10]; /* protocol */
14956 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14957 /* send join request to related PLCI */
14958 parms[i][1]=VSWITCHIE;
14959 parms[i][2]=VSWITCH_REQ;
14961 plci->relatedPTYPLCI->command = 0;
14962 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14963 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14964 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14965 send_req(plci->relatedPTYPLCI);
14966 break;
14967 case VSTRANSPORT:
14968 default:
14969 if(plci->relatedPTYPLCI &&
14970 plci->vswitchstate==3 &&
14971 plci->relatedPTYPLCI->vswitchstate==3)
14973 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14974 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14975 send_req(plci->relatedPTYPLCI);
14977 break;
14979 parms[i][0]=0; /* kill it */
14984 /*------------------------------------------------------------------*/
14986 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14987 ENTITY e;
14988 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14990 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14991 return (-1);
14994 pReq->xdi_dma_descriptor_operation.Req = 0;
14995 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14997 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14998 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
14999 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15000 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15002 e.user[0] = plci->adapter->Id - 1;
15003 plci->adapter->request((ENTITY*)pReq);
15005 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15006 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15007 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15008 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15009 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15010 plci->adapter->Id,
15011 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15012 *dma_magic));
15013 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15014 } else {
15015 dbug(1,dprintf("dma_alloc failed"));
15016 return (-1);
15020 static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15021 ENTITY e;
15022 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15024 if (nr < 0) {
15025 return;
15028 pReq->xdi_dma_descriptor_operation.Req = 0;
15029 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15031 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15032 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15033 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15034 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15036 e.user[0] = plci->adapter->Id - 1;
15037 plci->adapter->request((ENTITY*)pReq);
15039 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15040 dbug(1,dprintf("dma_free(%d)", nr));
15041 } else {
15042 dbug(1,dprintf("dma_free failed (%d)", nr));
15046 /*------------------------------------------------------------------*/