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)
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.
41 #define FILE_ "MESSAGE.C"
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);
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 {
263 byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
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] = {
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 */
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] = {
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)
393 DIVA_CAPI_ADAPTER * a;
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"));
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"));
415 a = &adapter[controller];
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);
424 || (plci->State == INC_CON_PENDING)
425 || (plci->State == INC_CON_ALERT)
426 || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
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;
435 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
436 i += MSG_IN_QUEUE_SIZE - j;
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;
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));
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)
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));
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)
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))
485 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
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));
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)"));
514 if (plci->req_in || plci->internal_command)
518 plci->command = msg->header.command;
519 plci->number = msg->header.number;
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));
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;
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));
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)) {
566 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
570 dbug(1,dprintf("BAD_MSG"));
571 if(plci) plci->command = 0;
576 c = ftable[i].function(GET_DWORD(&msg->header.controller),
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;
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)
601 for(i=0,p=0; format[i]; i++) {
604 parms[i].info = &msg[p];
619 parms[i].length = msg[p+1] + (msg[p+2]<<8);
620 p +=(parms[i].length +3);
623 parms[i].length = msg[p];
624 p +=(parms[i].length +1);
629 if(p>length) return true;
631 if(parms) parms[i].info = NULL;
635 void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
641 for (i = 0; format[i] != '\0'; i++)
643 out->parms[i].info = p;
644 out->parms[i].length = in[i].length;
657 n = in[i].length + 1;
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)
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)
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]);
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();
714 /*------------------------------------------------------------------*/
715 /* internal command queue */
716 /*------------------------------------------------------------------*/
718 static void init_internal_command_queue (PLCI *plci)
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)
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);
746 while (plci->internal_command_queue[i] != 0)
748 plci->internal_command_queue[i] = command_function;
753 static void next_internal_command (dword Id, PLCI *plci)
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)
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;
787 if (!ch || a->ch_ncci[ch])
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]));
800 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
805 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
807 if (ncci == MAX_NCCI+1)
814 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
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));
832 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
833 ncci_mapping_bug, ch, force_ncci));
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;
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));
855 static void ncci_free_receive_buffers (PLCI *plci, word ncci)
857 DIVA_CAPI_ADAPTER *a;
863 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
866 if (a->ncci_plci[ncci] == plci->Id)
871 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
872 ncci_mapping_bug, Id));
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;
891 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
893 if (a->ncci_plci[ncci] == plci->Id)
898 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
899 ncci_mapping_bug, Id));
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)
924 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
926 ncci_ptr = &(plci->adapter->ncci[ncci]);
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;
954 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
956 ncci_free_receive_buffers (plci, ncci);
959 if (a->ncci_plci[ncci] != plci->Id)
962 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
963 ncci_mapping_bug, Id, preserve_ncci));
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;
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))
979 if ((i != 0) && (a->ncci_next[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;
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;
1003 a->ncci_ch[ncci] = 0;
1004 a->ncci_plci[ncci] = 0;
1005 a->ncci_state[ncci] = IDLE;
1006 a->ncci_next[ncci] = 0;
1011 plci->ncci_ring_list = 0;
1016 /*------------------------------------------------------------------*/
1017 /* PLCI remove function */
1018 /*------------------------------------------------------------------*/
1020 static void plci_free_msg_in_queue (PLCI *plci)
1026 i = plci->msg_in_read_pos;
1027 while (i != plci->msg_in_write_pos)
1029 if (i == plci->msg_in_wrap_pos)
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)
1054 dbug(1,dprintf("plci_remove(no plci)"));
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))
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);
1074 if (!plci->sig_remove_id
1076 || (plci->req_in!=plci->req_out)
1077 || (plci->nl_req || plci->sig_req)))
1079 sig_req(plci,HANGUP,0);
1083 ncci_remove (plci, 0, false);
1084 plci_free_msg_in_queue (plci);
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)
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)
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)
1131 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
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'};
1160 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
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];
1177 for (k = 0; k < 8; k++)
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)
1207 API_PARSE ai_parms[5];
1211 static byte esc_chi[35] = {0x02,0x18,0x01};
1212 static byte lli[2] = {0x01,0x00};
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;
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);
1231 Info = _OUT_OF_PLCI;
1235 plci = &a->plci[i-1];
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) )
1244 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1251 if(bp->length)LinkLayer = bp->info[3];
1256 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
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]);
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);
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;
1305 Info = _WRONG_MESSAGE_FORMAT;
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];
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);
1360 /* D-Channel used for B3 connections */
1361 plci->Sig.Id = 0xff;
1365 if(!Info && ch!=2 && !noCh ) {
1366 Info = add_b23(plci,&parms[5]);
1368 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
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;
1382 dbug(1,dprintf("Spoof"));
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);
1394 plci->command = PERM_LIST_REQ;
1396 sig_req(plci,LISTEN_REQ,0);
1415 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1419 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1420 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1422 API_PARSE ai_parms[5];
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;
1433 dbug(1,dprintf("ai->length=%d",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)));
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);
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));
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);
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);
1496 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
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);
1507 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1509 Info = add_b23(plci, &parms[1]);
1512 dbug(1,dprintf("connect_res(error from add_b23)"));
1513 sig_req(plci,HANGUP,0);
1518 nl_req_ncci(plci, ASSIGN, 0);
1527 Info = add_b23(plci, &parms[1]);
1530 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1531 sig_req(plci,HANGUP,0);
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;
1544 dbug(1,dprintf("Spoof"));
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);
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"));
1577 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1582 dbug(1,dprintf("disconnect_req"));
1584 Info = _WRONG_IDENTIFIER;
1588 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1590 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
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)
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;
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;
1627 if(!appl) return false;
1628 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
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"));
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))
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) {
1659 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1664 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1666 Info = _WRONG_IDENTIFIER;
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];
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];
1692 else Info = 0x2002; /* wrong controller, codec not supported */
1694 else{ /* clear listen */
1695 a->codec_listen[appl->Id-1] = (PLCI *)0;
1704 if (a) listen_check(a);
1708 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1712 PLCI * rc_plci = NULL;
1713 API_PARSE ai_parms[5];
1716 dbug(1,dprintf("info_req"));
1717 for(i=0;i<5;i++) ai_parms[i].length = 0;
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;
1732 { /* no fac, with CPN, or KEY */
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);
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);
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"));
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);
1782 Info = _OUT_OF_PLCI;
1787 add_s(rc_plci,CPN,&msg[0]);
1788 add_ai(rc_plci, &msg[1]);
1789 sig_req(rc_plci,NCR_FACILITY,0);
1792 /* for application controlled supplementary services */
1798 Info = _WRONG_MESSAGE_FORMAT;
1806 { /* appl is not assigned to a PLCI or error condition */
1807 dbug(1,dprintf("localInfoCon"));
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"));
1823 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1828 dbug(1,dprintf("alert_req"));
1830 Info = _WRONG_IDENTIFIER;
1833 Info = _ALERT_IGNORED;
1834 if(plci->State!=INC_CON_ALERT) {
1835 Info = _WRONG_STATE;
1836 if(plci->State==INC_CON_PENDING) {
1838 plci->State=INC_CON_ALERT;
1839 add_ai(plci, &msg[0]);
1840 sig_req(plci,CALL_ALERT,0);
1853 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
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";
1866 API_PARSE ss_parms[11];
1872 dbug(1,dprintf("facility_req"));
1873 for(i=0;i<9;i++) ss_parms[i].length = 0;
1879 dbug(1,dprintf("wrong Ctrl"));
1880 Info = _WRONG_IDENTIFIER;
1883 selector = GET_WORD(msg[0].info);
1889 case SELECTOR_HANDSET:
1890 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1893 case SELECTOR_SU_SERV:
1896 Info = _WRONG_MESSAGE_FORMAT;
1899 SSreq = GET_WORD(&(msg[1].info[1]));
1900 PUT_WORD(&RCparms[1],SSreq);
1904 case S_GET_SUPPORTED_SERVICES:
1907 rplci = &a->plci[i-1];
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);
1916 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1917 SSparms = (byte *)SSstruct;
1920 rplci->internal_command = GETSERV_REQ_PEND;
1921 rplci->number = Number;
1923 sig_req(rplci,S_SUPPORTED,0);
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;
1940 Info = _WRONG_MESSAGE_FORMAT;
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? */
1948 rplci = &a->plci[i-1];
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);
1959 rplci->internal_command = GET_MWI_STATE;
1960 rplci->number = Number;
1961 sig_req(rplci,MWI_POLL,0);
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);
1977 else Info = 0x3010; /* wrong state */
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 */
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;
1999 dbug(1,dprintf("Spoof"));
2004 sig_req(plci,CALL_RETRIEVE,0);
2009 else Info = 0x3010; /* wrong state */
2014 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2016 dbug(1,dprintf("format wrong"));
2017 Info = _WRONG_MESSAGE_FORMAT;
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;
2029 else Info = 0x3010; /* wrong state */
2033 if(!(i=get_plci(a)) )
2035 Info = _OUT_OF_PLCI;
2038 rplci = &a->plci[i-1];
2040 rplci->number = Number;
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) )
2055 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2057 dbug(1,dprintf("format wrong"));
2059 Info = _WRONG_MESSAGE_FORMAT;
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);
2074 add_s(rplci,CAI,&ss_parms[2]);
2075 rplci->command = RESUME_REQ;
2076 sig_req(rplci,RESUME,0);
2077 rplci->State = RESUMING;
2081 case S_CONF_BEGIN: /* Request */
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;
2091 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2093 d = GET_DWORD(ss_parms[2].info);
2096 dbug(1,dprintf("format wrong"));
2097 Info = _WRONG_MESSAGE_FORMAT;
2100 plci->ptyState = (byte)SSreq;
2106 cai[1] = CONF_BEGIN;
2107 plci->internal_command = CONF_BEGIN_REQ_PEND;
2111 plci->internal_command = CONF_DROP_REQ_PEND;
2113 case S_CONF_ISOLATE:
2114 cai[1] = CONF_ISOLATE;
2115 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2117 case S_CONF_REATTACH:
2118 cai[1] = CONF_REATTACH;
2119 plci->internal_command = CONF_REATTACH_REQ_PEND;
2122 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2123 add_p(plci,CAI,cai);
2124 sig_req(plci,S_SERVICE,0);
2128 else Info = 0x3010; /* wrong state */
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;
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;
2155 Info = _WRONG_MESSAGE_FORMAT;
2160 Info = _WRONG_MESSAGE_FORMAT;
2165 Info = _WRONG_IDENTIFIER;
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"));
2183 Info = 0x3010; /* wrong state */
2189 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2190 relatedPLCIvalue >>=8;
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"));
2208 Info = 0x3010; /* wrong state */
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 )
2227 rplci->relatedPTYPLCI = plci;
2228 plci->relatedPTYPLCI = rplci;
2229 rplci->ptyState = (byte)SSreq;
2232 rplci->internal_command = ECT_REQ_PEND;
2233 cai[1] = ECT_EXECUTE;
2235 rplci->vswitchstate=0;
2237 rplci->vsprotdialect=0;
2238 plci->vswitchstate=0;
2240 plci->vsprotdialect=0;
2243 else if(SSreq==S_CONF_ADD)
2245 rplci->internal_command = CONF_ADD_REQ_PEND;
2250 rplci->internal_command = PTY_REQ_PEND;
2251 cai[1] = (byte)(SSreq-3);
2253 rplci->number = Number;
2254 if(plci!=rplci) /* explicit invocation */
2257 cai[2] = plci->Sig.Id;
2258 dbug(1,dprintf("explicit invocation"));
2262 dbug(1,dprintf("implicit invocation"));
2265 add_p(rplci,CAI,cai);
2266 sig_req(rplci,S_SERVICE,0);
2272 dbug(0,dprintf("Wrong line"));
2273 Info = 0x3010; /* wrong state */
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;
2287 Info = _WRONG_IDENTIFIER;
2290 /* reuse unused screening indicator */
2291 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2293 plci->internal_command = CD_REQ_PEND;
2294 appl->CDEnable = true;
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);
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;
2314 rplci = &a->plci[i-1];
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);
2323 Info = _OUT_OF_PLCI;
2327 /* reuse unused screening indicator */
2328 rplci->internal_command = CF_START_PEND;
2330 rplci->number = Number;
2331 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
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);
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:
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;
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;
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;
2374 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2376 dbug(0,dprintf("format wrong"));
2377 Info = _WRONG_MESSAGE_FORMAT;
2386 rplci = &a->plci[i-1];
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 */
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 */
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 */
2401 case S_CCBS_REQUEST:
2402 cai[1] = CCBS_REQUEST;
2403 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2405 case S_CCBS_DEACTIVATE:
2406 cai[1] = CCBS_DEACTIVATE;
2407 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2409 case S_CCBS_INTERROGATE:
2410 cai[1] = CCBS_INTERROGATE;
2411 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
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);
2426 Info = _OUT_OF_PLCI;
2430 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2433 case S_INTERROGATE_NUMBERS:
2435 add_p(rplci,CAI,cai);
2437 case S_CCBS_REQUEST:
2438 case S_CCBS_DEACTIVATE:
2440 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2441 add_p(rplci,CAI,cai);
2443 case S_CCBS_INTERROGATE:
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);
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);
2457 sig_req(rplci,S_SERVICE,0);
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;
2473 rplci = &a->plci[i-1];
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);
2483 Info = _OUT_OF_PLCI;
2490 rplci->cr_enquiry=false;
2494 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2496 rplci->number = Number;
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);
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;
2525 rplci = &a->plci[i-1];
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);
2535 Info = _OUT_OF_PLCI;
2542 rplci->cr_enquiry=false;
2546 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2548 rplci->number = Number;
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);
2562 Info = 0x300E; /* not supported */
2565 break; /* case SELECTOR_SU_SERV: end */
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:
2589 Info = _FACILITY_NOT_SUPPORTED;
2591 } /* end of switch(selector) */
2594 dbug(1,dprintf("SendFacRc"));
2596 _FACILITY_R|CONFIRM,
2599 "wws",Info,selector,SSparms);
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"));
2609 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2615 word fax_control_bits, fax_feature_bits, fax_info_change;
2619 API_PARSE fax_parms[9];
2623 dbug(1,dprintf("connect_b3_req"));
2626 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2627 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2629 Info = _WRONG_STATE;
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 */
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;
2648 _CONNECT_B3_R|CONFIRM,
2654 plci->requested_options_conn = 0;
2658 if(plci->B3_prot==2 || plci->B3_prot==3)
2663 if(ncpi->info[2] || ncpi->info[3])
2665 pvc[0] = ncpi->info[3];
2666 pvc[1] = ncpi->info[2];
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;
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;
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;
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;
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;
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];
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;
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);
2805 start_internal_command (Id, plci, fax_adjust_b23_command);
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);
2828 nl_req_ncci(plci,req,0);
2833 else Info = _WRONG_IDENTIFIER;
2836 _CONNECT_B3_R|CONFIRM,
2843 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2852 API_PARSE fax_parms[9];
2857 dbug(1,dprintf("connect_b3_res"));
2859 ncci = (word)(Id>>16);
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);
2871 a->ncci_state[ncci] = INC_ACT_PENDING;
2873 req = N_CONNECT_ACK;
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"));
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);
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","");
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);
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);
2958 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
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);
2978 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2984 dbug(1,dprintf("disconnect_b3_req"));
2986 Info = _WRONG_IDENTIFIER;
2987 ncci = (word)(Id>>16);
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;
3011 cleanup_ncci_data (plci, ncci);
3013 if(plci->B3_prot==2 || plci->B3_prot==3)
3018 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3021 nl_req_ncci(plci,N_DISC,(byte)ncci);
3027 _DISCONNECT_B3_R|CONFIRM,
3034 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3039 ncci = (word)(Id>>16);
3040 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",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){
3064 "ws", (word)3, "\x03\x04\x00\x00");
3065 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
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);
3090 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
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));
3106 Info = _WRONG_STATE;
3107 if ((a->ncci_state[ncci] == CONNECTED)
3108 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3111 ncci_ptr = &(a->ncci[ncci]);
3112 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3113 if (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)));
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)
3137 ncci_ptr->DataAck[i].Number = data->Number;
3138 ncci_ptr->DataAck[i].Handle = data->Handle;
3139 (ncci_ptr->data_ack_pending)++;
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))));
3162 "ww",GET_WORD(parms[2].info),Info);
3167 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3173 dbug(1,dprintf("data_b3_res"));
3175 ncci = (word)(Id>>16);
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);
3200 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3205 dbug(1,dprintf("reset_b3_req"));
3207 Info = _WRONG_IDENTIFIER;
3208 ncci = (word)(Id>>16);
3211 Info = _WRONG_STATE;
3212 switch (plci->B3_prot)
3216 if(a->ncci_state[ncci]==CONNECTED)
3218 nl_req_ncci(plci,N_RESET,(byte)ncci);
3223 case B3_TRANSPARENT:
3224 if(a->ncci_state[ncci]==CONNECTED)
3226 start_internal_command (Id, plci, reset_b3_command);
3232 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3234 _RESET_B3_R|CONFIRM,
3241 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3245 dbug(1,dprintf("reset_b3_res"));
3247 ncci = (word)(Id>>16);
3249 switch (plci->B3_prot)
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);
3265 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3271 dbug(1,dprintf("connect_b3_t90_a_res"));
3273 ncci = (word)(Id>>16);
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! */
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);
3299 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3304 API_PARSE bp_parms[7];
3308 Info = _WRONG_IDENTIFIER;
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;
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 */
3337 plci->State=INC_CON_CONNECTED_ALERT;
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);
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 */
3380 dbug(1,dprintf("continue if codec loaded"));
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);
3395 dbug(1,dprintf("Ext_Ctrl disable"));
3399 dbug(1,dprintf("Ext_Ctrl not requested"));
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);
3414 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3418 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3424 API_PARSE m_parms[5];
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 };
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);
3448 case _DI_ASSIGN_PLCI:
3449 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450 Info = _WRONG_MESSAGE_FORMAT;
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];
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);
3469 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3473 Info = add_b1(plci,&m_parms[3],0,0);
3476 add_p(plci,CAI,codec_cai);
3478 /* manual 'swich on' to the codec support without signalling */
3479 /* first 'assign plci' with this function, then use */
3481 if(AdvCodecSupport(a, plci, appl, 0) ) {
3482 Info = _RESOURCE_ERROR;
3485 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486 lli[1] = 0x10; /* local call codec stream */
3491 plci->State = LOCAL_CONNECT;
3492 plci->manufacturer = true;
3493 plci->command = _MANUFACTURER_R;
3494 plci->m_command = command;
3495 plci->number = Number;
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);
3506 Info = add_b23(plci,&m_parms[3]);
3509 nl_req_ncci(plci,ASSIGN,0);
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 */
3526 sig_req(plci,CALL_REQ,0);
3529 sig_req(plci,LISTEN_REQ,0);
3536 _MANUFACTURER_R|CONFIRM,
3539 "dww",_DI_MANU_ID,command,Info);
3545 else Info = _OUT_OF_PLCI;
3551 Info = _WRONG_IDENTIFIER;
3554 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555 Info = _WRONG_MESSAGE_FORMAT;
3558 req = m_parms[0].info[0];
3559 plci->command = _MANUFACTURER_R;
3560 plci->m_command = command;
3561 plci->number = Number;
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 */
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);
3583 if (plci->NL.Id && !plci->nl_remove_id)
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);
3605 /* signalling control for loop activation B-channel */
3608 Info = _WRONG_IDENTIFIER;
3612 plci->command = _MANUFACTURER_R;
3613 plci->number = Number;
3615 sig_req(plci,SIG_CTRL,0);
3618 else Info = _WRONG_MESSAGE_FORMAT;
3622 /* activation control for receiver/transmitter B-channel */
3625 Info = _WRONG_IDENTIFIER;
3629 plci->command = _MANUFACTURER_R;
3630 plci->number = Number;
3632 sig_req(plci,DSP_CTRL,0);
3635 else Info = _WRONG_MESSAGE_FORMAT;
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;
3651 v_plci = a->AdvCodecPLCI;
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;
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);
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;
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);
3704 Info = _WRONG_IDENTIFIER;
3708 add_ss(v_plci,FTY,m);
3709 sig_req(v_plci,TEL_CTRL,0);
3712 else Info = _WRONG_MESSAGE_FORMAT;
3716 case _DI_OPTIONS_REQUEST:
3717 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718 Info = _WRONG_MESSAGE_FORMAT;
3721 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3723 Info = _FACILITY_NOT_SUPPORTED;
3726 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3732 Info = _WRONG_MESSAGE_FORMAT;
3738 _MANUFACTURER_R|CONFIRM,
3741 "dww",_DI_MANU_ID,command,Info);
3746 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3750 API_PARSE m_parms[3];
3752 API_PARSE fax_parms[9];
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))
3765 indication = GET_WORD(msg[1].info);
3769 case _DI_NEGOTIATE_B3:
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"));
3778 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3780 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
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"));
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);
3817 /*------------------------------------------------------------------*/
3818 /* IDI callback function */
3819 /*------------------------------------------------------------------*/
3821 void callback(ENTITY * e)
3823 DIVA_CAPI_ADAPTER * a;
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)) {
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.
3864 dbug(1,dprintf("cancel RC in REMOVE state"));
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;
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;
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));
3901 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3903 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3911 control_rc (plci, 0, rc, ch, 0, true);
3916 channel_x_on (plci, ch);
3917 if (plci->internal_command)
3918 control_rc (plci, req, rc, ch, 0, true);
3922 if (plci->nl_global_req)
3924 global_req = plci->nl_global_req;
3925 plci->nl_global_req = 0;
3926 if (rc != ASSIGN_OK) {
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;
3942 if (plci->internal_command)
3943 control_rc (plci, req, rc, ch, 0, true);
3947 channel_xmit_xon (plci);
3948 control_rc (plci, req, rc, ch, 0, true);
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.
3964 dbug(1,dprintf("cancel RC in REMOVE state"));
3967 plci->sig_remove_id = 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)
3976 channel_xmit_xon (plci);
3977 control_rc (plci, 0, rc, ch, global_req, false);
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
3991 channel_xmit_xon(plci);
3992 goto capi_callback_suffix;
3996 channel_xmit_xon(plci);
3999 if (e->user[0] &0x8000) {
4000 byte Ind = e->Ind & 0x0f;
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;
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));
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;
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);
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));
4066 if (plci->li_notify_update)
4068 plci->li_notify_update = false;
4069 mixer_notify_update (plci, false);
4078 void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4086 DIVA_CAPI_ADAPTER * a;
4089 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4090 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4093 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
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"));
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"));
4111 ncci = a->ch_ncci[ch];
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))
4121 if(req==REMOVE && rc==ASSIGN_OK)
4123 sig_req(plci,HANGUP,0);
4124 sig_req(plci,REMOVE,0);
4129 switch(plci->command)
4132 dbug(1,dprintf("HoldRC=0x%x",rc));
4133 SSparms[1] = (byte)S_HOLD;
4136 plci->SuppState = IDLE;
4139 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4142 case C_RETRIEVE_REQ:
4143 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4144 SSparms[1] = (byte)S_RETRIEVE;
4147 plci->SuppState = CALL_HELD;
4150 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
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);
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)
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);
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);
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;
4193 case _CONNECT_I|RESPONSE:
4194 if (plci->State != INC_DIS_PENDING)
4195 plci->State = INC_CON_ACCEPT;
4199 if (plci->State == INC_DIS_PENDING)
4201 if(plci->Sig.Id!=0xff)
4203 plci->State = OUTG_DIS_PENDING;
4204 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4217 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4220 ncci = get_ncci (plci, ch, 0);
4221 Id = (Id & 0xffff) | (((dword) ncci) << 16);
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","");
4231 a->ncci_state[ncci] = OUTG_CON_PENDING;
4232 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4236 case _CONNECT_B3_I|RESPONSE:
4240 /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4243 case _DISCONNECT_B3_R:
4244 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4247 case _MANUFACTURER_R:
4253 Info = _WRONG_IDENTIFIER;
4254 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4258 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4266 else if (plci->internal_command)
4268 switch(plci->internal_command)
4274 if(rc==OK) /* command supported, wait for indication */
4281 /* Get Supported Services */
4282 case GETSERV_REQ_PEND:
4283 if(rc==OK) /* command supported, wait for indication */
4287 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4288 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
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;
4304 case INTERR_NUMBERS_REQ_PEND:
4305 SSparms[1] = S_INTERROGATE_NUMBERS;
4308 SSparms[1] = S_CALL_FORWARDING_START;
4311 SSparms[1] = S_CALL_FORWARDING_STOP;
4313 case CCBS_REQUEST_REQ_PEND:
4314 SSparms[1] = S_CCBS_REQUEST;
4316 case CCBS_DEACTIVATE_REQ_PEND:
4317 SSparms[1] = S_CCBS_DEACTIVATE;
4319 case CCBS_INTERROGATE_REQ_PEND:
4320 SSparms[1] = S_CCBS_INTERROGATE;
4323 if(global_req==ASSIGN)
4325 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4328 if(!plci->appl) break;
4329 if(rc==ISDN_GUARD_REJ)
4331 Info = _CAPI_GUARD_ERROR;
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);
4342 /* 3pty conference pending */
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;
4351 Info = 0x300E; /* not supported */
4352 plci->relatedPTYPLCI = NULL;
4356 _FACILITY_R|CONFIRM,
4359 "wws",Info,(word)3,SSparms);
4362 /* Explicit Call Transfer pending */
4364 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4365 if(!plci->relatedPTYPLCI) break;
4366 rplci = plci->relatedPTYPLCI;
4368 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4369 if(rplci->tel) rId|=EXT_CONTROLLER;
4372 Info = 0x300E; /* not supported */
4373 plci->relatedPTYPLCI = NULL;
4377 _FACILITY_R|CONFIRM,
4380 "wws",Info,(word)3,SSparms);
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 */
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 */
4403 case PERM_COD_HOOK: /* finished with Hook_Ind */
4407 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4408 plci->internal_command = PERM_COD_CONN_PEND;
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);
4416 plci->internal_command = PERM_COD_CALL;
4419 /* Null Call Reference Request pending */
4421 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4422 if(global_req==ASSIGN)
4430 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4431 appl->NullCREnable = false;
4435 else if(req==NCR_FACILITY)
4439 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4443 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4444 appl->NullCREnable = false;
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);
4464 if (plci->State == INC_DIS_PENDING)
4466 sig_req(plci,CALL_REQ,0);
4468 plci->State=OUTG_CON_PENDING;
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"));
4483 Info = 0x2007; /* Illegal message parameter coding */
4484 dbug(1,dprintf("MWI_REQ invalid parameter"));
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)
4504 _FACILITY_R|CONFIRM,
4507 "wws",Info,(word)3,SSparms);
4508 if(rc!=OK) plci_remove(plci);
4513 _FACILITY_R|CONFIRM,
4516 "wws",Info,(word)3,SSparms);
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;
4530 switch(plci->internal_command)
4532 case CONF_BEGIN_REQ_PEND:
4533 SSparms[1] = S_CONF_BEGIN;
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;
4540 case CONF_SPLIT_REQ_PEND:
4541 SSparms[1] = S_CONF_SPLIT;
4543 case CONF_DROP_REQ_PEND:
4544 SSparms[1] = S_CONF_DROP;
4546 case CONF_ISOLATE_REQ_PEND:
4547 SSparms[1] = S_CONF_ISOLATE;
4549 case CONF_REATTACH_REQ_PEND:
4550 SSparms[1] = S_CONF_REATTACH;
4556 Info = 0x300E; /* not supported */
4557 plci->relatedPTYPLCI = NULL;
4561 _FACILITY_R|CONFIRM,
4564 "wws",Info,(word)3,SSparms);
4567 case VSWITCH_REQ_PEND:
4570 if(plci->relatedPTYPLCI)
4572 plci->relatedPTYPLCI->vswitchstate=0;
4573 plci->relatedPTYPLCI->vsprot=0;
4574 plci->relatedPTYPLCI->vsprotdialect=0;
4576 plci->vswitchstate=0;
4578 plci->vsprotdialect=0;
4582 if(plci->relatedPTYPLCI &&
4583 plci->vswitchstate==1 &&
4584 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4585 plci->vswitchstate=3;
4589 /* Call Deflection Request pending (SSCT) */
4591 SSparms[1] = S_CALL_DEFLECTION;
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);
4601 case RTP_CONNECT_B3_REQ_COMMAND_2:
4604 ncci = get_ncci (plci, ch, 0);
4605 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4607 a->ncci_state[ncci] = OUTG_CON_PENDING;
4611 if (plci->internal_command_queue[0])
4613 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4614 if (plci->internal_command)
4619 next_internal_command (Id, plci);
4624 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4625 if(plci->tel) Id|=EXT_CONTROLLER;
4627 switch(plci->internal_command)
4632 case START_L1_SIG_ASSIGN_PEND:
4633 case REM_L1_SIG_ASSIGN_PEND:
4634 if(global_req == ASSIGN)
4640 dbug(1,dprintf("***L1 Req rem PLCI"));
4641 plci->internal_command = 0;
4642 sig_req(plci,REMOVE,0);
4647 /* Call Deflection Request pending, just no appl ptr assigned */
4649 SSparms[1] = S_CALL_DEFLECTION;
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;
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;
4670 case PERM_COD_HOOK: /* finished with Hook_Ind */
4674 plci->internal_command = PERM_COD_CONN_PEND;
4675 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
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);
4687 case LISTEN_SIG_ASSIGN_PEND:
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);
4698 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4706 if(global_req == ASSIGN)
4710 sig_req(plci,LAW_REQ,0);
4712 dbug(1,dprintf("Auto-Law assigned"));
4716 dbug(1,dprintf("Auto-Law assign failed"));
4717 a->automatic_law = 3;
4718 plci->internal_command = 0;
4719 a->automatic_lawPLCI = NULL;
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;
4731 dbug(1,dprintf("Auto-Law not supported"));
4732 a->automatic_law = 3;
4733 plci->internal_command = 0;
4734 sig_req(plci,REMOVE,0);
4736 a->automatic_lawPLCI = NULL;
4740 plci_remove_check(plci);
4744 void data_rc(PLCI * plci, byte ch)
4747 DIVA_CAPI_ADAPTER * a;
4754 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
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)
4783 DIVA_CAPI_ADAPTER * a;
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)
4816 DIVA_CAPI_ADAPTER * a;
4817 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4818 #define MAXPARMSIDS 31
4819 byte * parms[MAXPARMSIDS];
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];
4833 byte *esc_profile = "";
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) */
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};
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;
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"));
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)
4888 if(plci->Sig.Ind==HANGUP && plci->channels)
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"));
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--;
4905 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4909 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
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];
4931 esc_profile = parms[27];
4932 if(esc_cr[0] && plci)
4934 if(plci->cr_enquiry && plci->appl)
4936 plci->cr_enquiry = false;
4939 /* b = total length */
4940 /* b = indication type */
4941 /* b = length of all IEs */
4943 /* S = IE1 length + cont. */
4945 /* S = IE2 lenght + cont. */
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)
4966 dbug(0,dprintf("u-Law selected"));
4970 dbug(0,dprintf("a-Law selected"));
4973 a->automatic_law = 4;
4974 if(plci==a->automatic_lawPLCI) {
4975 plci->internal_command = 0;
4976 sig_req(plci,REMOVE,0);
4978 a->automatic_lawPLCI = NULL;
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;
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 */
5092 dbug(1,dprintf("S_Supported"));
5093 if(!plci->appl) break;
5096 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
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);
5108 /* Supplementary Service rejected */
5110 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5111 if(!pty_cai[0]) break;
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;
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]);
5139 PUT_WORD(&SS_Ind[4],0x300E);
5141 plci->relatedPTYPLCI = NULL;
5143 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5146 case CALL_DEFLECTION:
5147 if(pty_cai[2]!=0xff)
5149 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
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;
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:
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]);
5182 PUT_WORD(&Interr_Err_Ind[4],0x300E);
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);
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);
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);
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);
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);
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);
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);
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);
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]);
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);
5259 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5262 case CONF_ADD: /* ERROR */
5272 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5278 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5279 plci->ptyState = CONNECTED;
5284 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5285 plci->ptyState = CONNECTED;
5290 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5291 plci->ptyState = CONNECTED;
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;
5302 if(pty_cai[2]!=0xff)
5304 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
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);
5318 /* Supplementary Service indicates success */
5320 dbug(1,dprintf("Service_Ind"));
5321 PUT_WORD (&CF_Ind[4], 0);
5325 case THREE_PTY_BEGIN:
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;
5344 dbug(1,dprintf("ECT OK"));
5345 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5352 switch (plci->ptyState)
5355 plci->ptyState = CONNECTED;
5356 dbug(1,dprintf("3PTY ON"));
5360 plci->ptyState = IDLE;
5361 plci->relatedPTYPLCI = NULL;
5363 dbug(1,dprintf("3PTY OFF"));
5366 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5367 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
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;
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);
5392 case DIVERSION_INTERROGATE_CFU:
5393 case DIVERSION_INTERROGATE_CFB:
5394 case DIVERSION_INTERROGATE_CFNR:
5395 case DIVERSION_INTERROGATE_NUM:
5397 case CCBS_DEACTIVATE:
5398 case CCBS_INTERROGATE:
5399 if(!plci->appl) break;
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 */
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 */
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 */
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 */
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 */
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);
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);
5450 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
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]);
5467 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
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]);
5484 facility[2]= 0; /* returncode */
5486 else facility[2]= 0xff;
5491 facility[2]= 0xff; /* returncode */
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);
5500 next_internal_command (Id, plci);
5502 case CONF_ADD: /* OK */
5507 case CONF_PARTYDISC:
5513 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5517 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5521 PUT_DWORD(&CONF_Ind[6],0x0);
5525 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5530 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5535 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5540 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5542 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5543 tplci=plci->relatedPTYPLCI;
5544 if(tplci) tplci->ptyState = CONNECTED;
5546 case CONF_PARTYDISC:
5549 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5551 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5554 plci->ptyState = CONNECTED;
5555 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5557 case CCBS_INFO_RETAIN:
5558 case CCBS_ERASECALLLINKAGEID:
5559 case CCBS_STOP_ALERTING:
5564 case CCBS_INFO_RETAIN:
5565 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5567 case CCBS_STOP_ALERTING:
5568 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5570 case CCBS_ERASECALLLINKAGEID:
5571 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
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);
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);
5598 i = _L3_CAUSE | cau[2];
5599 if(cau[2]==0) 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);
5615 if(plci->SuppState == HOLD_REQUEST)
5617 plci->SuppState = CALL_HELD;
5618 CodecIdCheck(a, plci);
5619 start_internal_command (Id, plci, hold_save_command);
5623 case CALL_RETRIEVE_REJ:
5627 i = _L3_CAUSE | cau[2];
5628 if(cau[2]==0) 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);
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;
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);
5662 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5665 start_internal_command (Id, plci, retrieve_restore_command);
5670 if(plci->State != LISTENING) {
5671 sig_req(plci,HANGUP,0);
5675 cip = find_cip(a,parms[4],parms[6]);
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;
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)
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],
5729 SendSetupInfo(&application[i],
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);
5744 plci->notifiedcall = 0;
5749 case CALL_PEND_NOTIFY:
5750 plci->notifiedcall = 1;
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));
5770 tplci->internal_command = 0;
5771 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5772 switch (tplci->spoofed_msg)
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);
5791 case AWAITING_SELECT_B:
5792 dbug(1,dprintf("Select_B continue"));
5793 start_internal_command (x_Id, tplci, select_b_command);
5796 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
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);
5804 tplci->command = _MANUFACTURER_R;
5805 api_load_msg (&tplci->saved_msg, saved_parms);
5806 dir = saved_parms[2].info[0];
5808 sig_req(tplci,CALL_REQ,0);
5811 sig_req(tplci,LISTEN_REQ,0);
5814 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5817 case (CALL_REQ|AWAITING_MANUF_CON):
5818 sig_req(tplci,CALL_REQ,0);
5825 dbug(1,dprintf("No SigID!"));
5826 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
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);
5840 tplci->command = C_RETRIEVE_REQ;
5841 sig_req(tplci,CALL_RETRIEVE,0);
5845 tplci->spoofed_msg = 0;
5846 if (tplci->internal_command == 0)
5847 next_internal_command (x_Id, tplci);
5850 next_internal_command (Id, plci);
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);
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;
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 */
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);
5888 else /* ignore doubled hook indications */
5890 if( ((plci->hook_state)&0xf0)==0x80)
5892 dbug(1,dprintf("ignore hook"));
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;
5938 Id = ((word)tplci->Id<<8)|a->Id;
5944 "ws", (word)0, "\x01+");
5947 case 0x90: /* hook on */
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);
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,
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);
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);
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);
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);
6008 plci->hangup_flow_ctrl_timer=0;
6009 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
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;
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);
6032 clear_c_ind_mask (plci);
6036 if (plci->State == LISTENING)
6038 plci->notifiedcall=0;
6041 plci->State = INC_DIS_PENDING;
6042 if(c_ind_mask_empty (plci))
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);
6060 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6061 /* result in a second HANGUP! Don't generate another */
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);
6077 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6081 VSwitchReqInd(plci,Id,multi_vswitch_parms);
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);
6100 static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6105 byte * Info_Element;
6108 dbug(1,dprintf("SetupInfo"));
6110 for(i=0; i<MAXPARMSIDS; i++) {
6117 dbug(1,dprintf("CPN "));
6118 Info_Number = 0x0070;
6120 Info_Sent_Flag = true;
6122 case 8: /* display */
6123 dbug(1,dprintf("display(%d)",i));
6124 Info_Number = 0x0028;
6126 Info_Sent_Flag = true;
6128 case 16: /* Channel Id */
6129 dbug(1,dprintf("CHI"));
6130 Info_Number = 0x0018;
6132 Info_Sent_Flag = true;
6133 mixer_set_bchannel_id (plci, Info_Element);
6135 case 19: /* Redirected Number */
6136 dbug(1,dprintf("RDN"));
6137 Info_Number = 0x0074;
6139 Info_Sent_Flag = true;
6141 case 20: /* Redirected Number extended */
6142 dbug(1,dprintf("RDX"));
6143 Info_Number = 0x0073;
6145 Info_Sent_Flag = true;
6147 case 22: /* Redirecing Number */
6148 dbug(1,dprintf("RIN"));
6149 Info_Number = 0x0076;
6151 Info_Sent_Flag = true;
6159 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6160 Info_Number = 0x8000 |5;
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)
6181 byte * Info_Element;
6183 static byte charges[5] = {4,0,0,0,0};
6184 static byte cause[] = {0x02,0x80,0x00};
6187 dbug(1,dprintf("InfoParse "));
6192 && plci->Sig.Ind!=NCR_FACILITY
6195 dbug(1,dprintf("NoParse "));
6199 for(i=0; i<MAXPARMSIDS; i++) {
6206 dbug(1,dprintf("CPN "));
6207 Info_Number = 0x0070;
6210 case 7: /* ESC_CAU */
6211 dbug(1,dprintf("cau(0x%x)",ie[2]));
6212 Info_Number = 0x0008;
6215 Info_Element = NULL;
6217 case 8: /* display */
6218 dbug(1,dprintf("display(%d)",i));
6219 Info_Number = 0x0028;
6222 case 9: /* Date display */
6223 dbug(1,dprintf("date(%d)",i));
6224 Info_Number = 0x0029;
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;
6233 Info_Element = charges;
6235 case 11: /* user user info */
6236 dbug(1,dprintf("uui"));
6237 Info_Number = 0x007E;
6240 case 12: /* congestion receiver ready */
6241 dbug(1,dprintf("clRDY"));
6242 Info_Number = 0x00B0;
6246 case 13: /* congestion receiver not ready */
6247 dbug(1,dprintf("clNRDY"));
6248 Info_Number = 0x00BF;
6252 case 15: /* Keypad Facility */
6253 dbug(1,dprintf("KEY"));
6254 Info_Number = 0x002C;
6257 case 16: /* Channel Id */
6258 dbug(1,dprintf("CHI"));
6259 Info_Number = 0x0018;
6261 mixer_set_bchannel_id (plci, Info_Element);
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;
6268 if(cause[2] != ie[2]) Info_Element = cause;
6270 case 19: /* Redirected Number */
6271 dbug(1,dprintf("RDN"));
6272 Info_Number = 0x0074;
6275 case 22: /* Redirecing Number */
6276 dbug(1,dprintf("RIN"));
6277 Info_Number = 0x0076;
6280 case 23: /* Notification Indicator */
6281 dbug(1,dprintf("NI"));
6282 Info_Number = (word)NI;
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 */
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;
6305 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6307 for(j=0; j<max_appl; j++)
6309 appl = &application[j];
6312 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6314 dbug(1,dprintf("NCR_Ind"));
6316 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6320 else if(!plci->appl)
6321 { /* overlap receiving broadcast */
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"));
6334 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6338 } /* all other signalling states */
6340 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6342 dbug(1,dprintf("Std_Ind"));
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)
6356 byte * Info_Element;
6364 && plci->Sig.Ind!=NCR_FACILITY
6368 dbug(1,dprintf("NoM-IEParse "));
6371 dbug(1,dprintf("M-IEParse "));
6373 for(i=0; i<MAX_MULTI_IE; i++)
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];
6392 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
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))
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 */
6413 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6416 dbug(1,dprintf("Mlt_Std_Ind"));
6417 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6423 static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6426 /* Format of multi_ssext_parms[i][]:
6429 2 byte SSEXT_REQ/SSEXT_IND
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;
6446 parms[i][0]=0; /* kill it */
6447 sendf(appl,_MANUFACTURER_I,
6457 parms[i][0]=0; /* kill it */
6458 sendf(plci->appl,_MANUFACTURER_I,
6469 void nl_ind(PLCI * plci)
6474 DIVA_CAPI_ADAPTER * a;
6480 byte len, ncci_state;
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;
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"));
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"));
6577 if(plci->State < INC_ACT_PENDING)
6579 plci->NL.RNR = 1; /* flow control */
6580 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6585 if(!APPLptr) /* no application or invalid data */
6586 { /* while reloading the DSP */
6587 dbug(1,dprintf("discard1"));
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;
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))
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");
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");
6687 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6688 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6690 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6691 dtmf_confirmation (Id, plci);
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);
6700 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6701 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6706 case UDATA_INDICATION_MIXER_COEFS_SET:
6707 mixer_indication_coefs_set (Id, plci);
6709 case UDATA_INDICATION_XCONNECT_FROM:
6710 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6712 case UDATA_INDICATION_XCONNECT_TO:
6713 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6717 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6718 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
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,
6738 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6746 sendf(plci->appl,_DATA_B3_I,Id,0,
6749 plci->RData[0].PLength,
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)
6766 plci->ncpi_buffer[0] = 0;
6767 switch (plci->B3_prot) {
6770 break; /* no network control protocol info - jfr */
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;
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));
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];
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;
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];
6870 switch(plci->NL.Ind &0x0f) {
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)
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","");
6907 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6908 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
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","");
6920 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6921 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
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;
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","");
6948 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6949 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
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);
6963 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
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)
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","");
6985 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
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);
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","");
7017 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7018 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
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);
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 */
7055 && (plci->B1_resource == 16)
7056 && (plci->State <= CONNECTED))
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","");
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);
7087 plci->State = OUTG_DIS_PENDING;
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)
7098 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7099 if(plci->State == SUSPENDING){
7104 "ws", (word)3, "\x03\x04\x00\x00");
7105 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
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);
7121 plci->State = OUTG_DIS_PENDING;
7126 a->ncci_state[ncci] = INC_RES_PENDING;
7127 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7130 a->ncci_state[ncci] = CONNECTED;
7131 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
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;
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))
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);
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 */
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"));
7179 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7180 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7183 dbug(3,dprintf("DiscardData"));
7185 channel_x_off (plci, ch, 0);
7191 APPLptr->NCCIDataFlowCtrlTimer = 0;
7194 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7195 if(!plci->RData[0].P) {
7197 channel_x_off (plci, ch, 0);
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));
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;
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;
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;
7239 data_ack (plci, ch);
7247 /*------------------------------------------------------------------*/
7248 /* find a free PLCI */
7249 /*------------------------------------------------------------------*/
7251 word get_plci(DIVA_CAPI_ADAPTER * 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"));
7263 plci->Id = (byte)(i+1);
7271 plci->relatedPTYPLCI = NULL;
7273 plci->SuppState = IDLE;
7276 plci->B1_resource = 0;
7281 plci->m_command = 0;
7282 init_internal_command_queue (plci);
7284 plci->req_in_start = 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;
7298 plci->manufacturer = false;
7299 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7300 plci->spoofed_msg = 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;
7319 plci->vsprotdialect = 0;
7320 init_b1_config (plci);
7321 dbug(1,dprintf("get_plci(%x)",plci->Id));
7325 /*------------------------------------------------------------------*/
7326 /* put a parameter in the parameter buffer */
7327 /*------------------------------------------------------------------*/
7329 static void add_p(PLCI * plci, byte code, byte * p)
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)
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)
7370 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7372 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
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)
7388 if(!(code &0x80) && !p_length) return;
7390 if(plci->req_in==plci->req_in_start) {
7396 plci->RBuffer[plci->req_in++] = code;
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)
7414 if(plci->req_in==plci->req_in_start) {
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)
7431 API_PARSE ai_parms[5];
7433 for(i=0;i<5;i++) ai_parms[i].length = 0;
7437 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
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];
7455 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7456 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7459 API_PARSE mdm_cfg_v18[4];
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)"));
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)"));
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]));
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;
7502 plci->B1_resource = 0x5;
7503 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7504 add_p(plci, CAI, "\x01\x05");
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))
7534 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7537 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
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;
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);
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;
7571 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7573 add_p(plci, CAI, cai);
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));
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))
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))
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"));
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"));
7629 dbug(1,dprintf("MDM: no parity"));
7633 switch (GET_WORD (mdm_cfg[3].info))
7635 case 1: /* 2 stop bits */
7636 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7637 dbug(1,dprintf("MDM: 2 stop bits"));
7641 dbug(1,dprintf("MDM: 1 stop bit"));
7645 switch (GET_WORD (mdm_cfg[1].info))
7648 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7649 dbug(1,dprintf("MDM: 5 bits"));
7653 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7654 dbug(1,dprintf("MDM: 6 bits"));
7658 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7659 dbug(1,dprintf("MDM: 7 bits"));
7663 dbug(1,dprintf("MDM: 8 bits"));
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"));
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))
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);
7751 if (mdm_cfg[6].length >= 14)
7753 w = GET_WORD(&mdm_cfg[6].info[13]);
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]);
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]);
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]);
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 */
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];
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 */
7818 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7819 dbug(1,dprintf("56k sync HSCX"));
7824 else if(GET_WORD(bp_parms[0].info)==2){
7825 dbug(1,dprintf("56k async DSP"));
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 */
7853 return _B1_PARM_NOT_SUPPORTED;
7856 if (cai[1] == 13) /* v.110 async */
7858 if (bp_parms[3].length >= 8)
7860 switch (GET_WORD (&bp_parms[3].info[3]))
7863 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7866 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7869 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7872 switch (GET_WORD (&bp_parms[3].info[5]))
7874 case 1: /* odd parity */
7875 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7877 case 2: /* even parity */
7878 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7881 switch (GET_WORD (&bp_parms[3].info[7]))
7883 case 1: /* 2 stop bits */
7884 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7890 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7891 dbug(1,dprintf("V.110 default 56k sync"));
7897 dbug(1,dprintf("V.110 default 9600 async"));
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);
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;
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;
7943 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7945 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7948 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
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) {
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)) {
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*/;
7982 add_p(plci, LLC, llc);
7984 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7985 add_p(plci, DLC, dlc);
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*/;
7997 add_p(plci, LLC, llc);
7999 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8000 add_p(plci, DLC, dlc);
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;
8039 add_p(plci, LLC, llc);
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);
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))
8097 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8100 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8104 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8107 if (plci->B2_prot == B2_PIAFS)
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);
8120 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8121 header[GET_WORD(bp_parms[2].info)]);
8123 b1_config = &bp_parms[3];
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){
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 */
8166 if(b2_config->length >= 8) { /* PIAFS control abilities */
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 */
8174 else /* default values, 64K, variable, no compression */
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 */
8187 add_p(plci, DLC, dlc);
8191 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8193 if (plci->B3_prot != B3_TRANSPARENT)
8194 return _B_STACK_NOT_SUPPORTED;
8197 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
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){
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];
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]));
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;
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 */
8258 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8260 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8262 SAPI = b2_config->info[2]; /* SAPI */
8265 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8267 dlc[3] = 127; /* Mode */
8271 dlc[3] = 7; /* Mode */
8274 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
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;
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];
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){
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];
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]));
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 */
8381 if(i<b3_config_parms[2].length)
8383 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
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])));
8398 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
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;
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];
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;
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++];
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++];
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++];
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"));
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];
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;
8510 plci->fax_connect_info_buffer[len++] = nlc[++i];
8511 plci->fax_connect_info_length = len;
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];
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);
8536 /*----------------------------------------------------------------*/
8537 /* make the same as add_b23, but only for the modem related */
8538 /* L2 and L3 B-Chan protocol. */
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: */
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];
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",
8585 return (_WRONG_MESSAGE_FORMAT);
8587 b2_config = GET_WORD(mdm_config[0].info);
8590 /* OK, L2 is modem */
8594 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8596 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8599 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
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) {
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)) {
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);
8627 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
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;
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);
8684 /*------------------------------------------------------------------*/
8685 /* send a request for the signaling entity */
8686 /*------------------------------------------------------------------*/
8688 void sig_req(PLCI * plci, byte req, byte Id)
8691 if(plci->adapter->adapter_disabled) return;
8692 dbug(1,dprintf("sig_req(%x)",req));
8694 plci->sig_remove_id = plci->Sig.Id;
8695 if(plci->req_in==plci->req_in_start) {
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)
8713 if(plci->adapter->adapter_disabled) return;
8714 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8717 plci->nl_remove_id = plci->NL.Id;
8718 ncci_remove (plci, 0, (byte)(ncci != 0));
8721 if(plci->req_in==plci->req_in_start) {
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)
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]);
8750 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8752 if(plci->RBuffer[plci->req_out]==1)
8756 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8757 e->ReqCh = plci->RBuffer[plci->req_out++];
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;
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));
8773 if(plci->RBuffer[plci->req_out])
8774 e->Id = plci->RBuffer[plci->req_out];
8776 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8777 e->ReqCh = plci->RBuffer[plci->req_out++];
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;
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;
8795 if (!plci->nl_req && plci->ncci_ring_list)
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;
8822 plci->NData[0].P = v120_default_header;
8823 plci->NData[0].PLength = 1 ;
8825 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
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;
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);
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)
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))) {
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);
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 */
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 */
8940 /* w &=0xf0; removed, cannot detect congestion levels */
8941 /* upper 4 bit masked with w==SHIFT now */
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) {
8954 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8959 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
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]));
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);
8979 parms[mIEindex] = &in[ploc];
8982 mIEindex++; /* effects multiIEs only */
8991 /*------------------------------------------------------------------*/
8992 /* try to match a cip from received BC and HLC */
8993 /*------------------------------------------------------------------*/
8995 byte ie_compare(byte * ie1, byte * ie2)
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;
9004 word find_cip(DIVA_CAPI_ADAPTER * a, byte * bc, byte * hlc)
9009 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9012 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9018 static byte AddInfo(byte **add_i,
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 */
9038 add_i[0] = (byte *)"";
9042 add_i[3] = (byte *)"";
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]));
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])); */
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 */
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";
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);
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);
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)
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 */
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 */
9125 a->AdvSignalPLCI = plci;
9126 plci->tel=ADV_VOICE;
9128 return 0; /* adv codec still used */
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;
9141 splci->State = ADVANCED_VOICE_NOSIG;
9144 plci->spoofed_msg = SPOOFING_REQUIRED;
9146 /* indicate D-ch connect if */
9147 } /* codec is connected OK */
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);
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 */
9186 a->scom_appl_disable = true;
9189 return 0x2001; /* wrong state, no more plcis */
9193 else return 0x300B; /* Facility not supported */
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) {
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;
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)];
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];
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 /*------------------------------------------------------------------*/
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)
9298 if(a->automatic_law) {
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;
9311 sig_req(splci,ASSIGN,DSIG_ID);
9316 /* called from OS specific part if an application sends an Capi20Release */
9317 word CapiRelease(word Id)
9319 word i, j, appls_found;
9322 DIVA_CAPI_ADAPTER *a;
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 */
9340 for(i=0; i<max_adapter; i++) /* scan all adapters... */
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 */
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);
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))
9381 if(plci->appl==this)
9391 if(a->flag_dynamic_l1_down)
9393 if(appls_found==1) /* last application does a capi release */
9397 plci = &a->plci[j-1];
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);
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;
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)
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));
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);
9456 plci->notifiedcall = 0;
9458 listen_check(plci->adapter);
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 /*------------------------------------------------------------------*/
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);
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;
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)
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++)
9624 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9625 && (digit_buffer[i] != dtmf_digit_map[w].character))
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;
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));
9691 static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9695 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9696 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
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;
9710 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9711 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
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;
9728 static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9730 word internal_command, Info;
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));
9741 PUT_WORD (&result[1], DTMF_SUCCESS);
9742 internal_command = plci->internal_command;
9743 plci->internal_command = 0;
9745 switch (plci->dtmf_cmd)
9748 case DTMF_LISTEN_TONE_START:
9750 case DTMF_LISTEN_MF_START:
9753 case DTMF_LISTEN_START:
9754 switch (internal_command)
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;
9767 if (plci->internal_command)
9769 case DTMF_COMMAND_2:
9770 if (plci_nl_busy (plci))
9772 plci->internal_command = DTMF_COMMAND_2;
9775 plci->internal_command = DTMF_COMMAND_3;
9776 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
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;
9787 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9789 plci->dtmf_rec_active |= mask;
9795 case DTMF_LISTEN_TONE_STOP:
9797 case DTMF_LISTEN_MF_STOP:
9800 case DTMF_LISTEN_STOP:
9801 switch (internal_command)
9804 plci->dtmf_rec_active &= ~mask;
9805 if (plci->dtmf_rec_active)
9808 case DTMF_COMMAND_1:
9809 if (plci->dtmf_rec_active)
9811 if (plci_nl_busy (plci))
9813 plci->internal_command = DTMF_COMMAND_1;
9816 plci->dtmf_rec_active &= ~mask;
9817 plci->internal_command = DTMF_COMMAND_2;
9818 dtmf_enable_receiver (plci, false);
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;
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;
9841 if (plci->internal_command)
9848 case DTMF_SEND_TONE:
9853 case DTMF_DIGITS_SEND:
9854 switch (internal_command)
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)),
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;
9868 if (plci->internal_command)
9870 case DTMF_COMMAND_2:
9871 if (plci_nl_busy (plci))
9873 plci->internal_command = DTMF_COMMAND_2;
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);
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;
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)
9904 API_PARSE dtmf_parms[5];
9907 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9908 UnMapId (Id), (char *)(FILE_), __LINE__));
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);
9938 for (i = 0; i < 32; i++)
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));
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));
9961 else if (plci == NULL)
9963 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9964 UnMapId (Id), (char *)(FILE_), __LINE__));
9965 Info = _WRONG_IDENTIFIER;
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;
9979 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9981 switch (plci->dtmf_cmd)
9984 case DTMF_LISTEN_TONE_START:
9985 case DTMF_LISTEN_TONE_STOP:
9987 case DTMF_LISTEN_MF_START:
9988 case DTMF_LISTEN_MF_STOP:
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);
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;
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;
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);
10026 case DTMF_SEND_TONE:
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);
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;
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);
10054 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
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)))
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);
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;
10079 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10080 start_internal_command (Id, plci, dtmf_command);
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);
10096 static void dtmf_confirmation (dword Id, PLCI *plci)
10102 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10103 UnMapId (Id), (char *)(FILE_), __LINE__));
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)
10123 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10124 UnMapId (Id), (char *)(FILE_), __LINE__));
10127 for (i = 1; i < length; i++)
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)))
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))
10145 for (i = length; i > n + 1; i--)
10146 msg[i] = msg[i - 1];
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;
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)
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);
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));
10218 static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10222 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10223 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
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;
10235 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10238 dtmf_parameter_write (plci);
10239 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
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;
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)
10284 if (pchannelmap) *pchannelmap = 0;
10285 if(!chi[0]) return 0xff;
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 */
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 */
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;
10312 if((chi[0]-p)==4) ofs = 0;
10313 else if((chi[0]-p)==3) ofs = 1;
10317 for(i=0; i<4 && p<chi[0]; i++) {
10322 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10335 if((byte)(chi[0]-p)>30) return 0xfe;
10337 for(i=p; i<=chi[0]; i++) {
10338 if ((chi[i] &0x7f) > 31) return 0xfe;
10339 map |= (1L << (chi[i] &0x7f));
10343 if(p!=chi[0]) return 0xfe;
10344 if (ch > 31) return 0xfe;
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;
10361 if (pchannelmap) *pchannelmap = 2;
10364 if (pchannelmap) *pchannelmap = 4;
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;
10381 old_id = plci->li_bchannel_id;
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;
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;
10436 old_id = plci->li_bchannel_id;
10437 ch = chi_to_channel (chi, NULL);
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;
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'};
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;
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)
10659 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
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;
10676 for (j = 0; j < n; j++)
10678 if ((j & 0x7) == 0)
10680 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10681 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10684 dbug (1, dprintf ("[%06lx] CURRENT %s",
10685 (dword)(UnMapController (a->Id)), (char *) hex_line));
10687 for (j = 0; j < n; j++)
10689 if ((j & 0x7) == 0)
10691 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10692 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10695 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10696 (dword)(UnMapController (a->Id)), (char *) hex_line));
10698 for (j = 0; j < n; j++)
10700 if ((j & 0x7) == 0)
10702 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10703 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10706 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10707 (dword)(UnMapController (a->Id)), (char *) hex_line));
10708 for (i = 0; i < n; i++)
10711 for (j = 0; j < n; j++)
10713 if ((j & 0x7) == 0)
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];
10719 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10720 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10722 for (i = 0; i < n; i++)
10725 for (j = 0; j < n; j++)
10727 if ((j & 0x7) == 0)
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];
10733 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10734 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
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 }
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[] =
10800 19, /* Alt B to B */
10802 21, /* Alt PC to B */
10804 23, /* Alt IC to B */
10806 25, /* Alt B to PC */
10808 27, /* Alt PC to PC */
10810 29, /* Alt IC to PC */
10812 31, /* Alt B to IC */
10814 33, /* Alt PC 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 */
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;
10857 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10858 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10859 (char *)(FILE_), __LINE__));
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__));
10870 p = plci->internal_req_buffer;
10871 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10872 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10875 *(p++) = (byte)(w >> 8);
10876 w = ch | XCONNECT_CHANNEL_PORT_PC;
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;
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));
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__));
10920 i = a->li_base + (plci->li_bchannel_id - 1);
10921 j = plci->li_write_channel;
10922 p = plci->internal_req_buffer;
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));
10932 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
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)
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)
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))))))
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))
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)
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));
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);
10992 transfer_address = &(li_config_table[j].send_b);
10993 d = transfer_address->card_address.low;
10995 *(p++) = (byte)(d >> 8);
10996 *(p++) = (byte)(d >> 16);
10997 *(p++) = (byte)(d >> 24);
10998 d = transfer_address->card_address.high;
11000 *(p++) = (byte)(d >> 8);
11001 *(p++) = (byte)(d >> 16);
11002 *(p++) = (byte)(d >> 24);
11003 d = transfer_address->offset;
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;
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));
11017 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
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))
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)
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)
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))
11055 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
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;
11062 *(p++) = (byte)(w >> 8);
11066 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
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;
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;
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;
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];
11120 j = li_total_channels + 1;
11125 if (j <= li_total_channels)
11127 plci->internal_command = plci->li_write_command;
11128 if (plci_nl_busy (plci))
11130 if (j < a->li_base)
11134 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
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;
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;
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;
11172 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
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;
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;
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;
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];
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);
11238 static void mixer_notify_update (PLCI *plci, byte others)
11240 DIVA_CAPI_ADAPTER *a;
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));
11250 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11253 plci->li_notify_update = true;
11257 notify_plci = NULL;
11260 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11262 if (i < li_total_channels)
11263 notify_plci = li_config_table[i++].plci;
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)
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));
11306 plci->li_notify_update = false;
11311 static void mixer_clear_config (PLCI *plci)
11313 DIVA_CAPI_ADAPTER *a;
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;
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;
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;
11393 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11394 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
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;
11407 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11413 static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11415 DIVA_CAPI_ADAPTER *a;
11418 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11419 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
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;
11438 xconnect_query_addresses (plci);
11439 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11442 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
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;
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;
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;
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;
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;
11485 if (plci->internal_command)
11487 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11488 case ADJUST_B_RESTORE_MIXER_7:
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,
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)
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;
11532 if (plci->internal_command)
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);
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;
11574 if (plci->internal_command)
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;
11592 if (plci->internal_command)
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)));
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;
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;
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;
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;
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++)
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++)
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++)
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++)
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;
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;
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;
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)
11878 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11879 UnMapId (Id), (char *)(FILE_), __LINE__));
11880 return (_WRONG_IDENTIFIER);
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;
11895 static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11896 dword plci_b_id, word plci_b_write_pos, byte *p_result)
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);
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)))
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);
11925 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
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);
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);
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);
11958 static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11959 dword plci_b_id, word plci_b_write_pos, byte *p_result)
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);
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)))
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);
11988 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
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);
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);
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);
12021 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12025 dword d, li_flags, plci_b_id;
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];
12035 word plci_b_write_pos;
12037 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12038 UnMapId (Id), (char *)(FILE_), __LINE__));
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;
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);
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)
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)))
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);
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)
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)))
12129 PUT_DWORD (&result_buffer[18], d / 2);
12130 PUT_DWORD (&result_buffer[22], d - 1);
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;
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);
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)
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;
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;
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;
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;
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;
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);
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);
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);
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;
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);
12255 plci->li_cmd = GET_WORD (li_parms[0].info);
12256 start_internal_command (Id, plci, mixer_command);
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;
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);
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)
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;
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;
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;
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;
12313 while (participant_parms_pos < li_req_parms[0].length)
12315 result[result_pos] = 6;
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);
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);
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);
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;
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);
12374 plci->li_cmd = GET_WORD (li_parms[0].info);
12375 start_internal_command (Id, plci, mixer_command);
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__));
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__));
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;
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;
12408 plci->li_cmd = GET_WORD (li_parms[0].info);
12409 start_internal_command (Id, plci, mixer_command);
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);
12424 static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12427 DIVA_CAPI_ADAPTER *a;
12430 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12431 UnMapId (Id), (char *)(FILE_), __LINE__));
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)
12446 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12448 PUT_WORD (&result[4], _LI_USER_INITIATED);
12453 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12455 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12460 if (d & LI_PLCI_B_DISC_FLAG)
12463 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12465 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12466 PUT_WORD (&result[8], _LI_USER_INITIATED);
12471 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
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)
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));
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))
12507 if (ch & XCONNECT_CHANNEL_PORT_PC)
12508 p = &(li_config_table[j].send_pc);
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__));
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;
12558 static void mixer_remove (PLCI *plci)
12560 DIVA_CAPI_ADAPTER *a;
12565 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12566 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12567 (char *)(FILE_), __LINE__));
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)
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 (¶meter_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 (¶meter_buffer[4], w);
12627 add_p (plci, FTY, parameter_buffer);
12628 sig_req (plci, TEL_CTRL, 0);
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));
12665 static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12669 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12670 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
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;
12681 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12684 ec_write_parameters (plci);
12685 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
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;
12702 static void ec_command (dword Id, PLCI *plci, byte Rc)
12704 word internal_command, Info;
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));
12712 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12715 PUT_WORD (&result[1], EC_SUCCESS);
12720 PUT_WORD (&result[1], plci->ec_cmd);
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)
12735 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12736 B1_FACILITY_EC), 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;
12745 if (plci->internal_command)
12750 plci->internal_command = EC_COMMAND_2;
12753 plci->internal_command = EC_COMMAND_3;
12754 ec_write_parameters (plci);
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;
12768 case EC_DISABLE_OPERATION:
12769 switch (internal_command)
12773 if (plci->B1_facilities & B1_FACILITY_EC)
12777 plci->internal_command = EC_COMMAND_1;
12780 plci->internal_command = EC_COMMAND_2;
12781 ec_write_parameters (plci);
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;
12793 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12794 ~B1_FACILITY_EC), 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;
12803 if (plci->internal_command)
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)
12819 API_PARSE ec_parms[3];
12822 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12823 UnMapId (Id), (char *)(FILE_), __LINE__));
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;
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;
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;
12860 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12861 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
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);
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);
12894 case EC_FREEZE_COEFFICIENTS:
12895 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12896 start_internal_command (Id, plci, ec_command);
12899 case EC_RESUME_COEFFICIENT_UPDATE:
12900 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12901 start_internal_command (Id, plci, ec_command);
12904 case EC_RESET_COEFFICIENTS:
12905 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12906 start_internal_command (Id, plci, ec_command);
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);
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;
12927 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12930 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
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;
12952 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12953 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12955 PUT_WORD (&result[1], plci->ec_cmd);
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);
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);
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);
13005 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
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)
13017 PUT_WORD (&result[1], 0);
13020 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13021 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13023 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13024 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13026 case LEC_DISABLE_RELEASED:
13027 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13034 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13036 PUT_WORD (&result[4], 0);
13039 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13040 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13042 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13043 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13045 case LEC_DISABLE_RELEASED:
13046 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
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;
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));
13077 p = coef_buffer + 1;
13078 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13080 while (i + sizeof(word) <= a->adv_voice_coef_length)
13082 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13086 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13088 PUT_WORD (p, 0x8000);
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;
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);
13164 if (plci->B1_facilities & B1_FACILITY_MIXER)
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;
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;
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;
13199 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13200 *(p++) = a->adv_voice_coef_buffer[i];
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);
13216 static void adv_voice_clear_config (PLCI *plci)
13218 DIVA_CAPI_ADAPTER *a;
13223 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13224 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13225 (char *)(FILE_), __LINE__));
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));
13297 static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13299 DIVA_CAPI_ADAPTER *a;
13302 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13303 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
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;
13316 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13319 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13320 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
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;
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 */
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 */
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)
13423 switch (b1_resource)
13427 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13435 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13453 if (b1_facilities & B1_FACILITY_EC)
13455 if (b1_facilities & B1_FACILITY_LOCAL)
13457 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
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)
13469 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
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)
13486 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13493 if (b1_facilities & B1_FACILITY_LOCAL)
13495 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13505 if (b1_facilities & B1_FACILITY_LOCAL)
13507 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
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)));
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)
13576 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13577 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
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);
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;
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;
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)
13629 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
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)
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));
13660 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13663 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
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;
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;
13681 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
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)
13692 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
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)
13703 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
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)
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)
13718 plci->internal_command = plci->adjust_b_command;
13721 if (plci->adjust_b_parms_msg != NULL)
13722 api_load_msg (plci->adjust_b_parms_msg, bp);
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);
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));
13735 plci->internal_command = plci->adjust_b_command;
13736 sig_req (plci, RESOURCES, 0);
13738 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13741 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
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;
13752 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
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)
13762 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
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)
13774 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
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)
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;
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);
13800 api_load_msg (&plci->B_protocol, bp);
13801 Info = add_b23 (plci, bp);
13804 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13805 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13808 plci->internal_command = plci->adjust_b_command;
13809 nl_req_ncci (plci, ASSIGN, 0);
13811 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13814 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
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;
13824 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13826 if (Rc != ASSIGN_OK)
13828 plci->internal_command = plci->adjust_b_command;
13832 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13834 plci->adjust_b_restore = true;
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))
13844 nl_req_ncci (plci, N_CONNECT, 0);
13846 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13849 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
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;
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;
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;
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)
13896 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
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)
13913 plci->adjust_b_state = ADJUST_B_END;
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;
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)
13956 if (plci->req_in != 0)
13958 plci->internal_command = ADJUST_B_RESTORE_1;
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)
13989 static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
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));
13998 internal_command = plci->internal_command;
13999 plci->internal_command = 0;
14000 switch (internal_command)
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);
14016 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14017 UnMapId (Id), (char *)(FILE_), __LINE__));
14020 if (plci->internal_command)
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)
14032 word internal_command;
14035 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14036 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14039 internal_command = plci->internal_command;
14040 plci->internal_command = 0;
14041 switch (internal_command)
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;
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;
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);
14069 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14070 UnMapId (Id), (char *)(FILE_), __LINE__));
14073 if (plci->internal_command)
14075 if (plci->tel == ADV_VOICE)
14079 esc_chi[2] = plci->b_channel;
14080 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
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)
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));
14097 internal_command = plci->internal_command;
14098 plci->internal_command = 0;
14099 switch (internal_command)
14103 case FAX_CONNECT_ACK_COMMAND_1:
14104 if (plci_nl_busy (plci))
14106 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
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);
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));
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","");
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)
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));
14146 internal_command = plci->internal_command;
14147 plci->internal_command = 0;
14148 switch (internal_command)
14152 case FAX_EDATA_ACK_COMMAND_1:
14153 if (plci_nl_busy (plci))
14155 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
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);
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));
14177 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
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));
14186 internal_command = plci->internal_command;
14187 plci->internal_command = 0;
14188 switch (internal_command)
14192 case FAX_CONNECT_INFO_COMMAND_1:
14193 if (plci_nl_busy (plci))
14195 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
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);
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;
14214 if (plci_nl_busy (plci))
14216 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14219 plci->command = _CONNECT_B3_R;
14220 nl_req_ncci (plci, N_CONNECT, 0);
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)
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));
14237 internal_command = plci->internal_command;
14238 plci->internal_command = 0;
14239 switch (internal_command)
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);
14255 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14256 UnMapId (Id), (char *)(FILE_), __LINE__));
14259 if (plci->internal_command)
14261 case FAX_ADJUST_B23_COMMAND_2:
14262 if (plci_nl_busy (plci))
14264 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14267 plci->command = _CONNECT_B3_R;
14268 nl_req_ncci (plci, N_CONNECT, 0);
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)
14289 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
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));
14302 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14303 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14305 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14310 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14311 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14319 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
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));
14328 internal_command = plci->internal_command;
14329 plci->internal_command = 0;
14330 switch (internal_command)
14334 case RTP_CONNECT_B3_REQ_COMMAND_1:
14335 if (plci_nl_busy (plci))
14337 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14340 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14341 nl_req_ncci (plci, N_CONNECT, 0);
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;
14352 if (plci_nl_busy (plci))
14354 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
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);
14365 case RTP_CONNECT_B3_REQ_COMMAND_3:
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)
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));
14381 internal_command = plci->internal_command;
14382 plci->internal_command = 0;
14383 switch (internal_command)
14387 case RTP_CONNECT_B3_RES_COMMAND_1:
14388 if (plci_nl_busy (plci))
14390 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14393 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14394 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
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;
14405 if (plci_nl_busy (plci))
14407 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
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);
14419 case RTP_CONNECT_B3_RES_COMMAND_3:
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*/
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));
14436 internal_command = plci->internal_command;
14437 plci->internal_command = 0;
14438 switch (internal_command)
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);
14456 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14457 UnMapId (Id), (char *)(FILE_), __LINE__));
14460 if (plci->internal_command)
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*/
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));
14477 internal_command = plci->internal_command;
14478 plci->internal_command = 0;
14479 switch (internal_command)
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);
14495 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14496 UnMapId (Id), (char *)(FILE_), __LINE__));
14499 if (plci->internal_command)
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;
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)) {
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);
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);
14633 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
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;
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;
14659 static void channel_xmit_xon (PLCI * plci) {
14660 DIVA_CAPI_ADAPTER * a = plci->adapter;
14663 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14666 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
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;
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) {
14684 DIVA_CAPI_ADAPTER * a;
14690 APPLptr = plci->appl;
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 */
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)) {
14714 /*------------------------------------------------------------------*/
14716 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
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];
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"));
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++)
14774 auxplci = &a->plci[k];
14775 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
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 */
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;
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 */
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 */
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));
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;
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... */
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];
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);
14894 /*------------------------------------------------------------------*/
14896 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14898 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14901 /* Format of vswitch_t:
14904 2 byte VSWITCH_REQ/VSWITCH_IND
14906 4 word VSwitchcommand
14913 plci->Sig.Ind==NCR_FACILITY
14917 for(i=0;i<MAX_MULTI_IE;i++)
14919 if(!parms[i][0]) continue;
14922 parms[i][0]=0; /* kill it */
14925 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14926 switch(parms[i][4])
14929 if(!plci->relatedPTYPLCI ||
14930 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14934 /* remember all necessary informations */
14935 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
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 */
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);
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);
14979 parms[i][0]=0; /* kill it */
14984 /*------------------------------------------------------------------*/
14986 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
14988 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14990 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
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)",
15011 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15013 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15015 dbug(1,dprintf("dma_alloc failed"));
15020 static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15022 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
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));
15042 dbug(1,dprintf("dma_free failed (%d)", nr));
15046 /*------------------------------------------------------------------*/