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 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 void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci);
76 void set_group_ind_mask (PLCI *plci);
77 void set_group_ind_mask_bit (PLCI *plci, word b);
78 void clear_group_ind_mask_bit (PLCI *plci, word b);
79 byte test_group_ind_mask_bit (PLCI *plci, word b);
80 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
81 word CapiRelease(word);
82 word CapiRegister(word);
83 word api_put(APPL *, CAPI_MSG *);
84 static word api_parse(byte *, word, byte *, API_PARSE *);
85 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
86 static void api_load_msg(API_SAVE *in, API_PARSE *out);
88 word api_remove_start(void);
89 void api_remove_complete(void);
91 void plci_remove(PLCI *);
92 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a);
93 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
95 void callback(ENTITY *);
97 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
98 static void data_rc(PLCI *, byte);
99 static void data_ack(PLCI *, byte);
100 static void sig_ind(PLCI *);
101 static void SendInfo(PLCI *, dword, byte * *, byte);
102 static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte);
103 void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms);
105 void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
107 static void nl_ind(PLCI *);
109 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
132 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
134 static word get_plci(DIVA_CAPI_ADAPTER *);
135 static void add_p(PLCI *, byte, byte *);
136 static void add_s(PLCI * plci, byte code, API_PARSE * p);
137 static void add_ss(PLCI * plci, byte code, API_PARSE * p);
138 static void add_ie(PLCI * plci, byte code, byte * p, word p_length);
139 static void add_d(PLCI *, word, byte *);
140 static void add_ai(PLCI *, API_PARSE *);
141 static word add_b1(PLCI *, API_PARSE *, word, word);
142 static word add_b23(PLCI *, API_PARSE *);
143 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms);
144 static void sig_req(PLCI *, byte, byte);
145 static void nl_req_ncci(PLCI *, byte, byte);
146 static void send_req(PLCI *);
147 static void send_data(PLCI *);
148 static word plci_remove_check(PLCI *);
149 static void listen_check(DIVA_CAPI_ADAPTER *);
150 static byte AddInfo(byte **, byte **, byte *, byte *);
151 static byte getChannel(API_PARSE *);
152 static void IndParse(PLCI *, word *, byte **, byte);
153 static byte ie_compare(byte *, byte *);
154 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
155 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word);
160 static void channel_flow_control_remove (PLCI * plci);
161 static void channel_x_off (PLCI * plci, byte ch, byte flag);
162 static void channel_x_on (PLCI * plci, byte ch);
163 static void channel_request_xon (PLCI * plci, byte ch);
164 static void channel_xmit_xon (PLCI * plci);
165 static int channel_can_xon (PLCI * plci, byte ch);
166 static void channel_xmit_extended_xon (PLCI * plci);
168 static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse);
169 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
170 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
171 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * );
172 static void VoiceChannelOff(PLCI *plci);
173 static void adv_voice_write_coefs (PLCI *plci, word write_command);
174 static void adv_voice_clear_config (PLCI *plci);
176 static word get_b1_facilities (PLCI * plci, byte b1_resource);
177 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities);
178 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities);
179 static word adjust_b_process (dword Id, PLCI *plci, byte Rc);
180 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
181 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc);
182 static void reset_b3_command (dword Id, PLCI *plci, byte Rc);
183 static void select_b_command (dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc);
185 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc);
186 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc);
187 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc);
188 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc);
189 static void hold_save_command (dword Id, PLCI *plci, byte Rc);
190 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc);
191 static void init_b1_config (PLCI *plci);
192 static void clear_b1_config (PLCI *plci);
194 static void dtmf_command (dword Id, PLCI *plci, byte Rc);
195 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
196 static void dtmf_confirmation (dword Id, PLCI *plci);
197 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length);
198 static void dtmf_parameter_write (PLCI *plci);
201 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id);
202 static void mixer_set_bchannel_id (PLCI *plci, byte *chi);
203 static void mixer_clear_config (PLCI *plci);
204 static void mixer_notify_update (PLCI *plci, byte others);
205 static void mixer_command (dword Id, PLCI *plci, byte Rc);
206 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
207 static void mixer_indication_coefs_set (dword Id, PLCI *plci);
208 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length);
209 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length);
210 static void mixer_remove (PLCI *plci);
213 static void ec_command (dword Id, PLCI *plci, byte Rc);
214 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
215 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length);
218 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc);
219 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc);
222 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic);
223 static void diva_free_dma_descriptor (PLCI *plci, int nr);
225 /*------------------------------------------------------------------*/
226 /* external function prototypes */
227 /*------------------------------------------------------------------*/
229 extern byte MapController (byte);
230 extern byte UnMapController (byte);
231 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
232 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
234 void sendf(APPL *, word, dword, word, byte *, ...);
235 void * TransmitBufferSet(APPL * appl, dword ref);
236 void * TransmitBufferGet(APPL * appl, void * p);
237 void TransmitBufferFree(APPL * appl, void * p);
238 void * ReceiveBufferGet(APPL * appl, int Num);
240 int fax_head_line_time (char *buffer);
243 /*------------------------------------------------------------------*/
244 /* Global data definitions */
245 /*------------------------------------------------------------------*/
246 extern byte max_adapter;
247 extern byte max_appl;
248 extern DIVA_CAPI_ADAPTER * adapter;
249 extern APPL * application;
257 byte remove_started = FALSE;
264 byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
266 {_DATA_B3_R, "dwww", data_b3_req},
267 {_DATA_B3_I|RESPONSE, "w", data_b3_res},
268 {_INFO_R, "ss", info_req},
269 {_INFO_I|RESPONSE, "", info_res},
270 {_CONNECT_R, "wsssssssss", connect_req},
271 {_CONNECT_I|RESPONSE, "wsssss", connect_res},
272 {_CONNECT_ACTIVE_I|RESPONSE, "", connect_a_res},
273 {_DISCONNECT_R, "s", disconnect_req},
274 {_DISCONNECT_I|RESPONSE, "", disconnect_res},
275 {_LISTEN_R, "dddss", listen_req},
276 {_ALERT_R, "s", alert_req},
277 {_FACILITY_R, "ws", facility_req},
278 {_FACILITY_I|RESPONSE, "ws", facility_res},
279 {_CONNECT_B3_R, "s", connect_b3_req},
280 {_CONNECT_B3_I|RESPONSE, "ws", connect_b3_res},
281 {_CONNECT_B3_ACTIVE_I|RESPONSE, "", connect_b3_a_res},
282 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
283 {_DISCONNECT_B3_I|RESPONSE, "", disconnect_b3_res},
284 {_RESET_B3_R, "s", reset_b3_req},
285 {_RESET_B3_I|RESPONSE, "", reset_b3_res},
286 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "ws", connect_b3_t90_a_res},
287 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "", connect_b3_t90_a_res},
288 {_SELECT_B_REQ, "s", select_b_req},
289 {_MANUFACTURER_R, "dws", manufacturer_req},
290 {_MANUFACTURER_I|RESPONSE, "dws", manufacturer_res},
291 {_MANUFACTURER_I|RESPONSE, "", manufacturer_res}
294 byte * cip_bc[29][2] = {
296 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
297 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
298 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
299 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
300 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
301 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
302 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
303 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
304 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
312 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
313 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
320 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
321 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
322 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
323 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
324 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
327 byte * cip_hlc[29] = {
345 "\x02\x91\x81", /* 16 */
346 "\x02\x91\x84", /* 17 */
347 "\x02\x91\xa1", /* 18 */
348 "\x02\x91\xa4", /* 19 */
349 "\x02\x91\xa8", /* 20 */
350 "\x02\x91\xb1", /* 21 */
351 "\x02\x91\xb2", /* 22 */
352 "\x02\x91\xb5", /* 23 */
353 "\x02\x91\xb8", /* 24 */
354 "\x02\x91\xc1", /* 25 */
355 "\x02\x91\x81", /* 26 */
356 "\x03\x91\xe0\x01", /* 27 */
357 "\x03\x91\xe0\x02" /* 28 */
360 /*------------------------------------------------------------------*/
362 #define V120_HEADER_LENGTH 1
363 #define V120_HEADER_EXTEND_BIT 0x80
364 #define V120_HEADER_BREAK_BIT 0x40
365 #define V120_HEADER_C1_BIT 0x04
366 #define V120_HEADER_C2_BIT 0x08
367 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
369 static byte v120_default_header[] =
372 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
376 static byte v120_break_header[] =
379 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
384 /*------------------------------------------------------------------*/
385 /* API_PUT function */
386 /*------------------------------------------------------------------*/
388 word api_put(APPL * appl, CAPI_MSG * msg)
394 DIVA_CAPI_ADAPTER * a;
399 API_PARSE msg_parms[MAX_MSG_PARMS+1];
401 if (msg->header.length < sizeof (msg->header) ||
402 msg->header.length > MAX_MSG_SIZE) {
403 dbug(1,dprintf("bad len"));
407 controller = (byte)((msg->header.controller &0x7f)-1);
409 /* controller starts with 0 up to (max_adapter - 1) */
410 if ( controller >= max_adapter )
412 dbug(1,dprintf("invalid ctrl"));
416 a = &adapter[controller];
418 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
420 dbug(1,dprintf("plci=%x",msg->header.plci));
421 plci = &a->plci[msg->header.plci-1];
422 ncci = READ_WORD(&msg->header.ncci);
425 || (plci->State == INC_CON_PENDING)
426 || (plci->State == INC_CON_ALERT)
427 || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
429 || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
430 || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
432 i = plci->msg_in_read_pos;
433 j = plci->msg_in_write_pos;
436 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
437 i += MSG_IN_QUEUE_SIZE - j;
444 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
446 if (i > MSG_IN_QUEUE_SIZE - n)
447 i = MSG_IN_QUEUE_SIZE - n + 1;
451 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
454 dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
455 msg->header.length, plci->msg_in_write_pos,
456 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
461 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
462 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
464 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
467 if (msg->header.command == _DATA_B3_R)
469 if (msg->header.length < 20)
471 dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
474 ncci_ptr = &(a->ncci[ncci]);
475 n = ncci_ptr->data_pending;
476 l = ncci_ptr->data_ack_pending;
477 k = plci->msg_in_read_pos;
478 while (k != plci->msg_in_write_pos)
480 if (k == plci->msg_in_wrap_pos)
482 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
483 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
486 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
490 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
491 MSG_IN_OVERHEAD + 3) & 0xfffc;
494 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
496 dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
497 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
501 if (plci->req_in || plci->internal_command)
503 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
504 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
506 dbug(0,dprintf("Q-FULL3(requeue)"));
515 if (plci->req_in || plci->internal_command)
519 plci->command = msg->header.command;
520 plci->number = msg->header.number;
525 dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
526 msg->header.command, plci->req_in, plci->internal_command,
527 msg->header.length, plci->msg_in_write_pos,
528 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
530 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
531 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
532 for (i = 0; i < msg->header.length; i++)
533 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
534 if (m->header.command == _DATA_B3_R)
537 m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
541 j = (j + 3) & 0xfffc;
543 *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl;
544 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
553 dbug(1,dprintf("com=%x",msg->header.command));
555 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
556 for(i=0, ret = _BAD_MSG;
557 i<(sizeof(ftable)/sizeof(struct _ftable));
560 if(ftable[i].command==msg->header.command) {
561 /* break loop if the message is correct, otherwise continue scan */
562 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
563 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
567 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
571 dbug(1,dprintf("BAD_MSG"));
572 if(plci) plci->command = 0;
577 c = ftable[i].function(READ_DWORD(&msg->header.controller),
584 channel_xmit_extended_xon (plci);
586 if(c==1) send_req(plci);
587 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
588 if(plci && !plci->req_in) plci->command = 0;
593 /*------------------------------------------------------------------*/
594 /* api_parse function, check the format of api messages */
595 /*------------------------------------------------------------------*/
597 word api_parse(byte * msg, word length, byte * format, API_PARSE * parms)
602 for(i=0,p=0; format[i]; i++) {
605 parms[i].info = &msg[p];
620 parms[i].length = msg[p+1] + (msg[p+2]<<8);
621 p +=(parms[i].length +3);
624 parms[i].length = msg[p];
625 p +=(parms[i].length +1);
630 if(p>length) return TRUE;
632 if(parms) parms[i].info = NULL;
636 void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
642 for (i = 0; format[i] != '\0'; i++)
644 out->parms[i].info = p;
645 out->parms[i].length = in[i].length;
658 n = in[i].length + 1;
661 for (j = 0; j < n; j++)
662 *(p++) = in[i].info[j];
664 out->parms[i].info = NULL;
665 out->parms[i].length = 0;
668 void api_load_msg(API_SAVE *in, API_PARSE *out)
675 out[i].info = in->parms[i].info;
676 out[i].length = in->parms[i].length;
677 } while (in->parms[i++].info);
681 /*------------------------------------------------------------------*/
682 /* CAPI remove function */
683 /*------------------------------------------------------------------*/
685 word api_remove_start(void)
690 if(!remove_started) {
691 remove_started = TRUE;
692 for(i=0;i<max_adapter;i++) {
693 if(adapter[i].request) {
694 for(j=0;j<adapter[i].max_plci;j++) {
695 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
702 for(i=0;i<max_adapter;i++) {
703 if(adapter[i].request) {
704 for(j=0;j<adapter[i].max_plci;j++) {
705 if(adapter[i].plci[j].Sig.Id) return 1;
710 api_remove_complete();
715 /*------------------------------------------------------------------*/
716 /* internal command queue */
717 /*------------------------------------------------------------------*/
719 void init_internal_command_queue (PLCI *plci)
723 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
724 (char *)(FILE_), __LINE__));
726 plci->internal_command = 0;
727 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
728 plci->internal_command_queue[i] = NULL;
732 void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
736 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
737 UnMapId (Id), (char *)(FILE_), __LINE__));
739 if (plci->internal_command == 0)
741 plci->internal_command_queue[0] = command_function;
742 (* command_function)(Id, plci, OK);
747 while (plci->internal_command_queue[i] != 0)
749 plci->internal_command_queue[i] = command_function;
754 void next_internal_command (dword Id, PLCI *plci)
758 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
759 UnMapId (Id), (char *)(FILE_), __LINE__));
761 plci->internal_command = 0;
762 plci->internal_command_queue[0] = NULL;
763 while (plci->internal_command_queue[1] != 0)
765 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
766 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
767 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
768 (*(plci->internal_command_queue[0]))(Id, plci, OK);
769 if (plci->internal_command != 0)
771 plci->internal_command_queue[0] = NULL;
776 /*------------------------------------------------------------------*/
777 /* NCCI allocate/remove function */
778 /*------------------------------------------------------------------*/
780 static dword ncci_mapping_bug = 0;
782 static word get_ncci (PLCI *plci, byte ch, word force_ncci)
784 DIVA_CAPI_ADAPTER *a;
788 if (!ch || a->ch_ncci[ch])
791 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
792 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
801 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
806 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
808 if (ncci == MAX_NCCI+1)
815 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
823 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
825 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
826 if (i < MAX_NL_CHANNEL+1)
828 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
829 ncci_mapping_bug, ch, force_ncci, i, k, j));
833 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
834 ncci_mapping_bug, ch, force_ncci));
839 a->ncci_plci[ncci] = plci->Id;
840 a->ncci_state[ncci] = IDLE;
841 if (!plci->ncci_ring_list)
842 plci->ncci_ring_list = ncci;
844 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
845 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
847 a->ncci_ch[ncci] = ch;
848 a->ch_ncci[ch] = (byte) ncci;
849 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
850 ncci_mapping_bug, ch, force_ncci, ch, ncci));
856 static void ncci_free_receive_buffers (PLCI *plci, word ncci)
858 DIVA_CAPI_ADAPTER *a;
864 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
867 if (a->ncci_plci[ncci] == plci->Id)
872 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
873 ncci_mapping_bug, Id));
878 ncci_code = ncci | (((word) a->Id) << 8);
879 for (i = 0; i < appl->MaxBuffer; i++)
881 if ((appl->DataNCCI[i] == ncci_code)
882 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
884 appl->DataNCCI[i] = 0;
892 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
894 if (a->ncci_plci[ncci] == plci->Id)
899 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
900 ncci_mapping_bug, Id));
905 ncci_code = ncci | (((word) a->Id) << 8);
906 for (i = 0; i < appl->MaxBuffer; i++)
908 if ((appl->DataNCCI[i] == ncci_code)
909 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
911 appl->DataNCCI[i] = 0;
921 static void cleanup_ncci_data (PLCI *plci, word ncci)
925 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
927 ncci_ptr = &(plci->adapter->ncci[ncci]);
930 while (ncci_ptr->data_pending != 0)
932 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
933 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
934 (ncci_ptr->data_out)++;
935 if (ncci_ptr->data_out == MAX_DATA_B3)
936 ncci_ptr->data_out = 0;
937 (ncci_ptr->data_pending)--;
940 ncci_ptr->data_out = 0;
941 ncci_ptr->data_pending = 0;
942 ncci_ptr->data_ack_out = 0;
943 ncci_ptr->data_ack_pending = 0;
948 static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
950 DIVA_CAPI_ADAPTER *a;
955 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
957 ncci_free_receive_buffers (plci, ncci);
960 if (a->ncci_plci[ncci] != plci->Id)
963 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
964 ncci_mapping_bug, Id, preserve_ncci));
968 cleanup_ncci_data (plci, ncci);
969 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
970 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
971 a->ch_ncci[a->ncci_ch[ncci]] = 0;
974 a->ncci_ch[ncci] = 0;
975 a->ncci_plci[ncci] = 0;
976 a->ncci_state[ncci] = IDLE;
977 i = plci->ncci_ring_list;
978 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
980 if ((i != 0) && (a->ncci_next[i] == ncci))
983 plci->ncci_ring_list = 0;
984 else if (plci->ncci_ring_list == ncci)
985 plci->ncci_ring_list = i;
986 a->ncci_next[i] = a->ncci_next[ncci];
988 a->ncci_next[ncci] = 0;
994 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
996 if (a->ncci_plci[ncci] == plci->Id)
998 cleanup_ncci_data (plci, ncci);
999 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
1000 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
1001 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1004 a->ncci_ch[ncci] = 0;
1005 a->ncci_plci[ncci] = 0;
1006 a->ncci_state[ncci] = IDLE;
1007 a->ncci_next[ncci] = 0;
1012 plci->ncci_ring_list = 0;
1017 /*------------------------------------------------------------------*/
1018 /* PLCI remove function */
1019 /*------------------------------------------------------------------*/
1021 static void plci_free_msg_in_queue (PLCI *plci)
1027 i = plci->msg_in_read_pos;
1028 while (i != plci->msg_in_write_pos)
1030 if (i == plci->msg_in_wrap_pos)
1032 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1035 TransmitBufferFree (plci->appl,
1036 (byte *)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1040 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1041 MSG_IN_OVERHEAD + 3) & 0xfffc;
1045 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1046 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1047 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1051 void plci_remove(PLCI * plci)
1055 dbug(1,dprintf("plci_remove(no plci)"));
1058 init_internal_command_queue (plci);
1059 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1060 if(plci_remove_check(plci))
1064 if (plci->Sig.Id == 0xff)
1066 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1067 if (plci->NL.Id && !plci->nl_remove_id)
1069 nl_req_ncci(plci,REMOVE,0);
1075 if (!plci->sig_remove_id
1077 || (plci->req_in!=plci->req_out)
1078 || (plci->nl_req || plci->sig_req)))
1080 sig_req(plci,HANGUP,0);
1084 ncci_remove (plci, 0, FALSE);
1085 plci_free_msg_in_queue (plci);
1089 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1090 plci->State = OUTG_DIS_PENDING;
1093 /*------------------------------------------------------------------*/
1094 /* Application Group function helpers */
1095 /*------------------------------------------------------------------*/
1097 void set_group_ind_mask (PLCI *plci)
1101 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1102 plci->group_optimization_mask_table[i] = 0xffffffffL;
1105 void set_group_ind_mask_bit (PLCI *plci, word b)
1107 plci->group_optimization_mask_table[b >> 5] |= (1L << (b & 0x1f));
1110 void clear_group_ind_mask_bit (PLCI *plci, word b)
1112 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1115 byte test_group_ind_mask_bit (PLCI *plci, word b)
1117 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1120 /*------------------------------------------------------------------*/
1121 /* c_ind_mask operations for arbitrary MAX_APPL */
1122 /*------------------------------------------------------------------*/
1124 void clear_c_ind_mask (PLCI *plci)
1128 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1129 plci->c_ind_mask_table[i] = 0;
1132 byte c_ind_mask_empty (PLCI *plci)
1137 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1139 return (i == C_IND_MASK_DWORDS);
1142 void set_c_ind_mask_bit (PLCI *plci, word b)
1144 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1147 void clear_c_ind_mask_bit (PLCI *plci, word b)
1149 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1152 byte test_c_ind_mask_bit (PLCI *plci, word b)
1154 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1157 void dump_c_ind_mask (PLCI *plci)
1159 static char hex_digit_table[0x10] =
1160 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1166 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1170 for (j = 0; j < 4; j++)
1172 if (i+j < C_IND_MASK_DWORDS)
1174 d = plci->c_ind_mask_table[i+j];
1175 for (k = 0; k < 8; k++)
1177 *(--p) = hex_digit_table[d & 0xf];
1183 for (k = 0; k < 8; k++)
1188 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1196 #define dump_plcis(a)
1200 /*------------------------------------------------------------------*/
1201 /* translation function for each message */
1202 /*------------------------------------------------------------------*/
1204 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1213 API_PARSE ai_parms[5];
1217 static byte esc_chi[35] = {0x02,0x18,0x01};
1218 static byte lli[2] = {0x01,0x00};
1223 for(i=0;i<5;i++) ai_parms[i].length = 0;
1225 dbug(1,dprintf("connect_req(%d)",parms->length));
1226 Info = _WRONG_IDENTIFIER;
1229 if(a->adapter_disabled)
1231 dbug(1,dprintf("adapter disabled"));
1232 Id = ((word)1<<8)|a->Id;
1233 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1234 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1237 Info = _OUT_OF_PLCI;
1241 plci = &a->plci[i-1];
1243 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1244 /* check 'external controller' bit for codec support */
1245 if(Id & EXT_CONTROLLER)
1247 if(AdvCodecSupport(a, plci, appl, 0) )
1250 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1257 if(bp->length)LinkLayer = bp->info[3];
1262 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1265 if(ai_parms[0].length)
1267 ch = READ_WORD(ai_parms[0].info+1);
1268 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1269 if(ch==4) /* explizit CHI in message */
1271 /* check length of B-CH struct */
1272 if((ai_parms[0].info)[3]>=1)
1274 if((ai_parms[0].info)[4]==CHI)
1276 p_chi = &((ai_parms[0].info)[5]);
1280 p_chi = &((ai_parms[0].info)[3]);
1282 if(p_chi[0]>35) /* check length of channel ID */
1284 Info = _WRONG_MESSAGE_FORMAT;
1287 else Info = _WRONG_MESSAGE_FORMAT;
1290 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1292 dir = READ_WORD(ai_parms[0].info+3);
1295 for(i=0; i+5<=ai_parms[0].length; i++)
1297 if(ai_parms[0].info[i+5]!=0)
1299 if((ai_parms[0].info[i+5] | m) != 0xff)
1300 Info = _WRONG_MESSAGE_FORMAT;
1311 Info = _WRONG_MESSAGE_FORMAT;
1314 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1316 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1317 for(i=0; i+5<=ai_parms[0].length; i++)
1318 esc_chi[i+3] = ai_parms[0].info[i+5];
1322 esc_chi[2] = (byte)channel;
1323 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1324 add_p(plci,LLI,lli);
1325 add_p(plci,ESC,esc_chi);
1326 plci->State = LOCAL_CONNECT;
1327 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1332 else Info = _WRONG_MESSAGE_FORMAT;
1335 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1336 plci->command = _CONNECT_R;
1337 plci->number = Number;
1338 /* x.31 or D-ch free SAPI in LinkLayer? */
1339 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = TRUE;
1340 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1342 /* B-channel used for B3 connections (ch==0), or no B channel */
1343 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1344 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1345 else Info = add_b1(plci,&parms[5],ch,0);
1346 add_s(plci,OAD,&parms[2]);
1347 add_s(plci,OSA,&parms[4]);
1348 add_s(plci,BC,&parms[6]);
1349 add_s(plci,LLC,&parms[7]);
1350 add_s(plci,HLC,&parms[8]);
1351 CIP = READ_WORD(parms[0].info);
1352 if (a->Info_Mask[appl->Id-1] & 0x200)
1354 /* early B3 connect (CIP mask bit 9) no release after a disc */
1355 add_p(plci,LLI,"\x01\x01");
1357 if(READ_WORD(parms[0].info)<29) {
1358 add_p(plci,BC,cip_bc[READ_WORD(parms[0].info)][a->u_law]);
1359 add_p(plci,HLC,cip_hlc[READ_WORD(parms[0].info)]);
1361 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1362 sig_req(plci,ASSIGN,DSIG_ID);
1366 /* D-Channel used for B3 connections */
1367 plci->Sig.Id = 0xff;
1371 if(!Info && ch!=2 && !noCh ) {
1372 Info = add_b23(plci,&parms[5]);
1374 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1380 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1382 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1384 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1385 plci->spoofed_msg = CALL_REQ;
1386 plci->internal_command = BLOCK_PLCI;
1388 dbug(1,dprintf("Spoof"));
1392 if(ch==4)add_p(plci,CHI,p_chi);
1393 add_s(plci,CPN,&parms[1]);
1394 add_s(plci,DSA,&parms[3]);
1395 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1396 add_ai(plci,&parms[9]);
1397 if(!dir)sig_req(plci,CALL_REQ,0);
1400 plci->command = PERM_LIST_REQ;
1402 sig_req(plci,LISTEN_REQ,0);
1421 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1425 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1426 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1428 API_PARSE ai_parms[5];
1432 dbug(1,dprintf("connect_res(no plci)"));
1433 return 0; /* no plci, no send */
1436 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1437 for(i=0;i<5;i++) ai_parms[i].length = 0;
1439 dbug(1,dprintf("ai->length=%d",ai->length));
1443 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1445 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,READ_WORD(ai_parms[0].info+1)));
1447 if(ai_parms[0].length)
1449 ch = READ_WORD(ai_parms[0].info+1);
1450 dbug(1,dprintf("BCH-I=0x%x",ch));
1455 if(plci->State==INC_CON_CONNECTED_ALERT)
1457 dbug(1,dprintf("Connected Alert Call_Res"));
1458 if (a->Info_Mask[appl->Id-1] & 0x200)
1460 /* early B3 connect (CIP mask bit 9) no release after a disc */
1461 add_p(plci,LLI,"\x01\x01");
1463 add_s(plci, CONN_NR, &parms[2]);
1464 add_s(plci, LLC, &parms[4]);
1465 add_ai(plci, &parms[5]);
1466 plci->State = INC_CON_ACCEPT;
1467 sig_req(plci, CALL_RES,0);
1470 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1471 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1472 dump_c_ind_mask (plci);
1473 Reject = READ_WORD(parms[0].info);
1474 dbug(1,dprintf("Reject=0x%x",Reject));
1477 if(c_ind_mask_empty (plci))
1479 if((Reject&0xff00)==0x3400)
1481 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1482 add_p(plci,ESC,esc_t);
1483 add_ai(plci, &parms[5]);
1484 sig_req(plci,REJECT,0);
1486 else if(Reject==1 || Reject>9)
1488 add_ai(plci, &parms[5]);
1489 sig_req(plci,HANGUP,0);
1493 esc_t[2] = cau_t[(Reject&0x000f)];
1494 add_p(plci,ESC,esc_t);
1495 add_ai(plci, &parms[5]);
1496 sig_req(plci,REJECT,0);
1502 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1507 if(Id & EXT_CONTROLLER){
1508 if(AdvCodecSupport(a, plci, appl, 0)){
1509 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1510 sig_req(plci,HANGUP,0);
1513 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1515 Info = add_b23(plci, &parms[1]);
1518 dbug(1,dprintf("connect_res(error from add_b23)"));
1519 sig_req(plci,HANGUP,0);
1524 nl_req_ncci(plci, ASSIGN, 0);
1533 Info = add_b23(plci, &parms[1]);
1536 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1537 sig_req(plci,HANGUP,0);
1541 nl_req_ncci(plci, ASSIGN, 0);
1544 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1546 api_save_msg(parms, "wsssss", &plci->saved_msg);
1547 plci->spoofed_msg = CALL_RES;
1548 plci->internal_command = BLOCK_PLCI;
1550 dbug(1,dprintf("Spoof"));
1554 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1555 if (a->Info_Mask[appl->Id-1] & 0x200)
1557 /* early B3 connect (CIP mask bit 9) no release after a disc */
1558 add_p(plci,LLI,"\x01\x01");
1560 add_s(plci, CONN_NR, &parms[2]);
1561 add_s(plci, LLC, &parms[4]);
1562 add_ai(plci, &parms[5]);
1563 plci->State = INC_CON_ACCEPT;
1564 sig_req(plci, CALL_RES,0);
1567 for(i=0; i<max_appl; i++) {
1568 if(test_c_ind_mask_bit (plci, i)) {
1569 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1577 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1579 dbug(1,dprintf("connect_a_res"));
1583 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1588 dbug(1,dprintf("disconnect_req"));
1590 Info = _WRONG_IDENTIFIER;
1594 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1596 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1598 for(i=0; i<max_appl; i++)
1600 if(test_c_ind_mask_bit (plci, i))
1601 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1603 plci->State = OUTG_DIS_PENDING;
1605 if(plci->Sig.Id && plci->appl)
1608 if(plci->Sig.Id!=0xff)
1610 if(plci->State!=INC_DIS_PENDING)
1612 add_ai(plci, &msg[0]);
1613 sig_req(plci,HANGUP,0);
1614 plci->State = OUTG_DIS_PENDING;
1620 if (plci->NL.Id && !plci->nl_remove_id)
1622 mixer_remove (plci);
1623 nl_req_ncci(plci,REMOVE,0);
1624 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1625 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1626 plci->State = INC_DIS_PENDING;
1633 if(!appl) return FALSE;
1634 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1638 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1640 dbug(1,dprintf("disconnect_res"));
1643 /* clear ind mask bit, just in case of collsion of */
1644 /* DISCONNECT_IND and CONNECT_RES */
1645 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1646 ncci_free_receive_buffers (plci, 0);
1647 if(plci_remove_check(plci))
1651 if(plci->State==INC_DIS_PENDING
1652 || plci->State==SUSPENDING) {
1653 if(c_ind_mask_empty (plci)) {
1654 if(plci->State!=SUSPENDING)plci->State = IDLE;
1655 dbug(1,dprintf("chs=%d",plci->channels));
1656 if(!plci->channels) {
1665 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
1670 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1672 Info = _WRONG_IDENTIFIER;
1675 a->Info_Mask[appl->Id-1] = READ_DWORD(parms[0].info);
1676 a->CIP_Mask[appl->Id-1] = READ_DWORD(parms[1].info);
1677 dbug(1,dprintf("CIP_MASK=0x%lx",READ_DWORD(parms[1].info)));
1678 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1679 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1682 /* check if external controller listen and switch listen on or off*/
1683 if(Id&EXT_CONTROLLER && READ_DWORD(parms[1].info)){
1684 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1685 dummy_plci.State = IDLE;
1686 a->codec_listen[appl->Id-1] = &dummy_plci;
1687 a->TelOAD[0] = (byte)(parms[3].length);
1688 for(i=1;parms[3].length>=i && i<22;i++) {
1689 a->TelOAD[i] = parms[3].info[i];
1692 a->TelOSA[0] = (byte)(parms[4].length);
1693 for(i=1;parms[4].length>=i && i<22;i++) {
1694 a->TelOSA[i] = parms[4].info[i];
1698 else Info = 0x2002; /* wrong controller, codec not supported */
1700 else{ /* clear listen */
1701 a->codec_listen[appl->Id-1] = (PLCI *)0;
1710 if (a) listen_check(a);
1714 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1718 PLCI * rc_plci = NULL;
1719 API_PARSE ai_parms[5];
1722 dbug(1,dprintf("info_req"));
1723 for(i=0;i<5;i++) ai_parms[i].length = 0;
1729 if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1731 dbug(1,dprintf("AddInfo wrong"));
1732 Info = _WRONG_MESSAGE_FORMAT;
1735 if(!a) Info = _WRONG_STATE;
1738 { /* no fac, with CPN, or KEY */
1740 if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1742 /* overlap sending option */
1743 dbug(1,dprintf("OvlSnd"));
1744 add_s(plci,CPN,&msg[0]);
1745 add_s(plci,KEY,&ai_parms[1]);
1746 sig_req(plci,INFO_REQ,0);
1751 if(plci->State && ai_parms[2].length)
1753 /* User_Info option */
1754 dbug(1,dprintf("UUI"));
1755 add_s(plci,UUI,&ai_parms[2]);
1756 sig_req(plci,USER_DATA,0);
1758 else if(plci->State && ai_parms[3].length)
1760 /* Facility option */
1761 dbug(1,dprintf("FAC"));
1762 add_s(plci,CPN,&msg[0]);
1763 add_ai(plci, &msg[1]);
1764 sig_req(plci,FACILITY_REQ,0);
1768 Info = _WRONG_STATE;
1771 else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1773 /* NCR_Facility option -> send UUI and Keypad too */
1774 dbug(1,dprintf("NCR_FAC"));
1777 rc_plci = &a->plci[i-1];
1778 appl->NullCREnable = TRUE;
1779 rc_plci->internal_command = C_NCR_FAC_REQ;
1780 rc_plci->appl = appl;
1781 add_p(rc_plci,CAI,"\x01\x80");
1782 add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1783 sig_req(rc_plci,ASSIGN,DSIG_ID);
1788 Info = _OUT_OF_PLCI;
1793 add_s(rc_plci,CPN,&msg[0]);
1794 add_ai(rc_plci, &msg[1]);
1795 sig_req(rc_plci,NCR_FACILITY,0);
1798 /* for application controlled supplementary services */
1804 Info = _WRONG_MESSAGE_FORMAT;
1812 { /* appl is not assigned to a PLCI or error condition */
1813 dbug(1,dprintf("localInfoCon"));
1823 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1825 dbug(1,dprintf("info_res"));
1829 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1834 dbug(1,dprintf("alert_req"));
1836 Info = _WRONG_IDENTIFIER;
1839 Info = _ALERT_IGNORED;
1840 if(plci->State!=INC_CON_ALERT) {
1841 Info = _WRONG_STATE;
1842 if(plci->State==INC_CON_PENDING) {
1844 plci->State=INC_CON_ALERT;
1845 add_ai(plci, &msg[0]);
1846 sig_req(plci,CALL_ALERT,0);
1859 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
1866 long relatedPLCIvalue;
1867 DIVA_CAPI_ADAPTER * relatedadapter;
1868 byte * SSparms = "";
1869 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1870 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1872 API_PARSE ss_parms[11];
1878 dbug(1,dprintf("facility_req"));
1879 for(i=0;i<9;i++) ss_parms[i].length = 0;
1885 dbug(1,dprintf("wrong Ctrl"));
1886 Info = _WRONG_IDENTIFIER;
1889 selector = READ_WORD(msg[0].info);
1895 case SELECTOR_HANDSET:
1896 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1899 case SELECTOR_SU_SERV:
1902 Info = _WRONG_MESSAGE_FORMAT;
1905 SSreq = READ_WORD(&(msg[1].info[1]));
1906 WRITE_WORD(&RCparms[1],SSreq);
1910 case S_GET_SUPPORTED_SERVICES:
1913 rplci = &a->plci[i-1];
1915 add_p(rplci,CAI,"\x01\x80");
1916 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1917 sig_req(rplci,ASSIGN,DSIG_ID);
1922 WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1923 SSparms = (byte *)SSstruct;
1926 rplci->internal_command = GETSERV_REQ_PEND;
1927 rplci->number = Number;
1929 sig_req(rplci,S_SUPPORTED,0);
1935 if(parms->length==7)
1937 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1939 dbug(1,dprintf("format wrong"));
1940 Info = _WRONG_MESSAGE_FORMAT;
1946 Info = _WRONG_MESSAGE_FORMAT;
1949 a->Notification_Mask[appl->Id-1] = READ_DWORD(ss_parms[2].info);
1950 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1954 rplci = &a->plci[i-1];
1956 add_p(rplci,CAI,"\x01\x80");
1957 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1958 sig_req(rplci,ASSIGN,DSIG_ID);
1965 rplci->internal_command = GET_MWI_STATE;
1966 rplci->number = Number;
1967 sig_req(rplci,MWI_POLL,0);
1973 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1974 if(plci && plci->State && plci->SuppState==IDLE)
1976 plci->SuppState = HOLD_REQUEST;
1977 plci->command = C_HOLD_REQ;
1978 add_s(plci,CAI,&ss_parms[1]);
1979 sig_req(plci,CALL_HOLD,0);
1983 else Info = 0x3010; /* wrong state */
1986 if(plci && plci->State && plci->SuppState==CALL_HELD)
1988 if(Id & EXT_CONTROLLER)
1990 if(AdvCodecSupport(a, plci, appl, 0))
1992 Info = 0x3010; /* wrong state */
1998 plci->SuppState = RETRIEVE_REQUEST;
1999 plci->command = C_RETRIEVE_REQ;
2000 if(plci->spoofed_msg==SPOOFING_REQUIRED)
2002 plci->spoofed_msg = CALL_RETRIEVE;
2003 plci->internal_command = BLOCK_PLCI;
2005 dbug(1,dprintf("Spoof"));
2010 sig_req(plci,CALL_RETRIEVE,0);
2015 else Info = 0x3010; /* wrong state */
2020 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2022 dbug(1,dprintf("format wrong"));
2023 Info = _WRONG_MESSAGE_FORMAT;
2027 if(plci && plci->State)
2029 add_s(plci,CAI,&ss_parms[2]);
2030 plci->command = SUSPEND_REQ;
2031 sig_req(plci,SUSPEND,0);
2032 plci->State = SUSPENDING;
2035 else Info = 0x3010; /* wrong state */
2039 if(!(i=get_plci(a)) )
2041 Info = _OUT_OF_PLCI;
2044 rplci = &a->plci[i-1];
2046 rplci->number = Number;
2048 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2049 /* check 'external controller' bit for codec support */
2050 if(Id & EXT_CONTROLLER)
2052 if(AdvCodecSupport(a, rplci, appl, 0) )
2061 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2063 dbug(1,dprintf("format wrong"));
2065 Info = _WRONG_MESSAGE_FORMAT;
2070 dummy.info = "\x00";
2071 add_b1(rplci, &dummy, 0, 0);
2072 if (a->Info_Mask[appl->Id-1] & 0x200)
2074 /* early B3 connect (CIP mask bit 9) no release after a disc */
2075 add_p(rplci,LLI,"\x01\x01");
2077 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2078 sig_req(rplci,ASSIGN,DSIG_ID);
2080 add_s(rplci,CAI,&ss_parms[2]);
2081 rplci->command = RESUME_REQ;
2082 sig_req(rplci,RESUME,0);
2083 rplci->State = RESUMING;
2087 case S_CONF_BEGIN: /* Request */
2089 case S_CONF_ISOLATE:
2090 case S_CONF_REATTACH:
2091 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2093 dbug(1,dprintf("format wrong"));
2094 Info = _WRONG_MESSAGE_FORMAT;
2097 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2099 d = READ_DWORD(ss_parms[2].info);
2102 dbug(1,dprintf("format wrong"));
2103 Info = _WRONG_MESSAGE_FORMAT;
2106 plci->ptyState = (byte)SSreq;
2112 cai[1] = CONF_BEGIN;
2113 plci->internal_command = CONF_BEGIN_REQ_PEND;
2117 plci->internal_command = CONF_DROP_REQ_PEND;
2119 case S_CONF_ISOLATE:
2120 cai[1] = CONF_ISOLATE;
2121 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2123 case S_CONF_REATTACH:
2124 cai[1] = CONF_REATTACH;
2125 plci->internal_command = CONF_REATTACH_REQ_PEND;
2128 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2129 add_p(plci,CAI,cai);
2130 sig_req(plci,S_SERVICE,0);
2134 else Info = 0x3010; /* wrong state */
2141 if(parms->length==7)
2143 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2145 dbug(1,dprintf("format wrong"));
2146 Info = _WRONG_MESSAGE_FORMAT;
2150 else if(parms->length==8) /* workaround for the T-View-S */
2152 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2154 dbug(1,dprintf("format wrong"));
2155 Info = _WRONG_MESSAGE_FORMAT;
2161 Info = _WRONG_MESSAGE_FORMAT;
2166 Info = _WRONG_MESSAGE_FORMAT;
2171 Info = _WRONG_IDENTIFIER;
2174 relatedPLCIvalue = READ_DWORD(ss_parms[2].info);
2175 relatedPLCIvalue &= 0x0000FFFF;
2176 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2177 /* controller starts with 0 up to (max_adapter - 1) */
2178 if (((relatedPLCIvalue & 0x7f) == 0)
2179 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2180 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2182 if(SSreq==S_3PTY_END)
2184 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2189 Info = 0x3010; /* wrong state */
2195 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2196 relatedPLCIvalue >>=8;
2198 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2200 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2202 rplci = &relatedadapter->plci[i];
2205 if(!rplci || !relatedPLCIvalue)
2207 if(SSreq==S_3PTY_END)
2209 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2214 Info = 0x3010; /* wrong state */
2220 dbug(1,dprintf("rplci:%x",rplci));
2221 dbug(1,dprintf("plci:%x",plci));
2222 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2223 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2224 dbug(1,dprintf("SSreq:%x",SSreq));
2225 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2226 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2227 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2229 /* send PTY/ECT req, cannot check all states because of US stuff */
2230 if( !rplci->internal_command && rplci->appl )
2233 rplci->relatedPTYPLCI = plci;
2234 plci->relatedPTYPLCI = rplci;
2235 rplci->ptyState = (byte)SSreq;
2238 rplci->internal_command = ECT_REQ_PEND;
2239 cai[1] = ECT_EXECUTE;
2241 rplci->vswitchstate=0;
2243 rplci->vsprotdialect=0;
2244 plci->vswitchstate=0;
2246 plci->vsprotdialect=0;
2249 else if(SSreq==S_CONF_ADD)
2251 rplci->internal_command = CONF_ADD_REQ_PEND;
2256 rplci->internal_command = PTY_REQ_PEND;
2257 cai[1] = (byte)(SSreq-3);
2259 rplci->number = Number;
2260 if(plci!=rplci) /* explicit invocation */
2263 cai[2] = plci->Sig.Id;
2264 dbug(1,dprintf("explicit invocation"));
2268 dbug(1,dprintf("implicit invocation"));
2271 add_p(rplci,CAI,cai);
2272 sig_req(rplci,S_SERVICE,0);
2278 dbug(0,dprintf("Wrong line"));
2279 Info = 0x3010; /* wrong state */
2284 case S_CALL_DEFLECTION:
2285 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2287 dbug(1,dprintf("format wrong"));
2288 Info = _WRONG_MESSAGE_FORMAT;
2293 Info = _WRONG_IDENTIFIER;
2296 /* reuse unused screening indicator */
2297 ss_parms[3].info[3] = (byte)READ_WORD(&(ss_parms[2].info[0]));
2299 plci->internal_command = CD_REQ_PEND;
2300 appl->CDEnable = TRUE;
2302 cai[1] = CALL_DEFLECTION;
2303 add_p(plci,CAI,cai);
2304 add_p(plci,CPN,ss_parms[3].info);
2305 sig_req(plci,S_SERVICE,0);
2310 case S_CALL_FORWARDING_START:
2311 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2313 dbug(1,dprintf("format wrong"));
2314 Info = _WRONG_MESSAGE_FORMAT;
2320 rplci = &a->plci[i-1];
2322 add_p(rplci,CAI,"\x01\x80");
2323 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2324 sig_req(rplci,ASSIGN,DSIG_ID);
2329 Info = _OUT_OF_PLCI;
2333 /* reuse unused screening indicator */
2334 rplci->internal_command = CF_START_PEND;
2336 rplci->number = Number;
2337 appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0]));
2339 cai[1] = 0x70|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
2340 cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2341 add_p(rplci,CAI,cai);
2342 add_p(rplci,OAD,ss_parms[5].info);
2343 add_p(rplci,CPN,ss_parms[6].info);
2344 sig_req(rplci,S_SERVICE,0);
2349 case S_INTERROGATE_DIVERSION:
2350 case S_INTERROGATE_NUMBERS:
2351 case S_CALL_FORWARDING_STOP:
2352 case S_CCBS_REQUEST:
2353 case S_CCBS_DEACTIVATE:
2354 case S_CCBS_INTERROGATE:
2357 case S_INTERROGATE_NUMBERS:
2358 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2360 dbug(0,dprintf("format wrong"));
2361 Info = _WRONG_MESSAGE_FORMAT;
2364 case S_CCBS_REQUEST:
2365 case S_CCBS_DEACTIVATE:
2366 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2368 dbug(0,dprintf("format wrong"));
2369 Info = _WRONG_MESSAGE_FORMAT;
2372 case S_CCBS_INTERROGATE:
2373 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2375 dbug(0,dprintf("format wrong"));
2376 Info = _WRONG_MESSAGE_FORMAT;
2380 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2382 dbug(0,dprintf("format wrong"));
2383 Info = _WRONG_MESSAGE_FORMAT;
2392 rplci = &a->plci[i-1];
2395 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2396 cai[1] = 0x60|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
2397 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2399 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2400 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2401 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2403 case S_CALL_FORWARDING_STOP:
2404 rplci->internal_command = CF_STOP_PEND;
2405 cai[1] = 0x80|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
2407 case S_CCBS_REQUEST:
2408 cai[1] = CCBS_REQUEST;
2409 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2411 case S_CCBS_DEACTIVATE:
2412 cai[1] = CCBS_DEACTIVATE;
2413 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2415 case S_CCBS_INTERROGATE:
2416 cai[1] = CCBS_INTERROGATE;
2417 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2424 rplci->number = Number;
2425 add_p(rplci,CAI,"\x01\x80");
2426 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2427 sig_req(rplci,ASSIGN,DSIG_ID);
2432 Info = _OUT_OF_PLCI;
2436 appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0]));
2439 case S_INTERROGATE_NUMBERS:
2441 add_p(rplci,CAI,cai);
2443 case S_CCBS_REQUEST:
2444 case S_CCBS_DEACTIVATE:
2446 WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0])));
2447 add_p(rplci,CAI,cai);
2449 case S_CCBS_INTERROGATE:
2451 WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0])));
2452 add_p(rplci,CAI,cai);
2453 add_p(rplci,OAD,ss_parms[4].info);
2457 cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2458 add_p(rplci,CAI,cai);
2459 add_p(rplci,OAD,ss_parms[5].info);
2463 sig_req(rplci,S_SERVICE,0);
2468 case S_MWI_ACTIVATE:
2469 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2471 dbug(1,dprintf("format wrong"));
2472 Info = _WRONG_MESSAGE_FORMAT;
2479 rplci = &a->plci[i-1];
2481 rplci->cr_enquiry=TRUE;
2482 add_p(rplci,CAI,"\x01\x80");
2483 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2484 sig_req(rplci,ASSIGN,DSIG_ID);
2489 Info = _OUT_OF_PLCI;
2496 rplci->cr_enquiry=FALSE;
2500 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2502 rplci->number = Number;
2505 cai[1] = ACTIVATION_MWI; /* Function */
2506 WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2507 WRITE_DWORD(&cai[4],READ_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2508 WRITE_WORD(&cai[8],READ_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2509 WRITE_WORD(&cai[10],READ_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2510 WRITE_WORD(&cai[12],READ_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2511 add_p(rplci,CAI,cai);
2512 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2513 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2514 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2515 add_p(rplci,UID,ss_parms[10].info); /* Time */
2516 sig_req(rplci,S_SERVICE,0);
2520 case S_MWI_DEACTIVATE:
2521 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2523 dbug(1,dprintf("format wrong"));
2524 Info = _WRONG_MESSAGE_FORMAT;
2531 rplci = &a->plci[i-1];
2533 rplci->cr_enquiry=TRUE;
2534 add_p(rplci,CAI,"\x01\x80");
2535 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2536 sig_req(rplci,ASSIGN,DSIG_ID);
2541 Info = _OUT_OF_PLCI;
2548 rplci->cr_enquiry=FALSE;
2552 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2554 rplci->number = Number;
2557 cai[1] = DEACTIVATION_MWI; /* Function */
2558 WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2559 WRITE_WORD(&cai[4],READ_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2560 add_p(rplci,CAI,cai);
2561 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2562 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2563 sig_req(rplci,S_SERVICE,0);
2568 Info = 0x300E; /* not supported */
2571 break; /* case SELECTOR_SU_SERV: end */
2575 return (dtmf_request (Id, Number, a, plci, appl, msg));
2579 case SELECTOR_LINE_INTERCONNECT:
2580 return (mixer_request (Id, Number, a, plci, appl, msg));
2584 case PRIV_SELECTOR_ECHO_CANCELLER:
2585 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2586 return (ec_request (Id, Number, a, plci, appl, msg));
2588 case SELECTOR_ECHO_CANCELLER:
2589 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2590 return (ec_request (Id, Number, a, plci, appl, msg));
2593 case SELECTOR_V42BIS:
2595 Info = _FACILITY_NOT_SUPPORTED;
2597 } /* end of switch(selector) */
2600 dbug(1,dprintf("SendFacRc"));
2602 _FACILITY_R|CONFIRM,
2605 "wws",Info,selector,SSparms);
2609 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
2611 dbug(1,dprintf("facility_res"));
2615 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2621 word fax_control_bits, fax_feature_bits, fax_info_change;
2625 API_PARSE fax_parms[9];
2629 dbug(1,dprintf("connect_b3_req"));
2632 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2633 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2635 Info = _WRONG_STATE;
2639 /* local reply if assign unsuccessfull
2640 or B3 protocol allows only one layer 3 connection
2641 and already connected
2642 or B2 protocol not any LAPD
2643 and connect_b3_req contradicts originate/answer direction */
2645 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2646 && ((plci->channels != 0)
2647 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2648 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2650 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2651 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2652 Info = _WRONG_STATE;
2654 _CONNECT_B3_R|CONFIRM,
2660 plci->requested_options_conn = 0;
2664 if(plci->B3_prot==2 || plci->B3_prot==3)
2669 if(ncpi->info[2] || ncpi->info[3])
2671 pvc[0] = ncpi->info[3];
2672 pvc[1] = ncpi->info[2];
2678 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2679 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2683 else if(plci->B3_prot==5)
2685 if (plci->NL.Id && !plci->nl_remove_id)
2687 fax_control_bits = READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2688 fax_feature_bits = READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2689 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2690 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2692 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2693 fax_info_change = FALSE;
2694 if (ncpi->length >= 4)
2696 w = READ_WORD(&ncpi->info[3]);
2697 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2699 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2700 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2701 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2702 fax_info_change = TRUE;
2704 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2705 if (w & 0x0002) /* Fax-polling request */
2706 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2707 if ((w & 0x0004) /* Request to send / poll another document */
2708 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2710 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2712 if (ncpi->length >= 6)
2714 w = READ_WORD(&ncpi->info[5]);
2715 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2717 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2718 fax_info_change = TRUE;
2721 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2722 && (READ_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2724 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2726 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2727 && (READ_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2729 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2731 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2732 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2733 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2734 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2736 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2737 Info = _WRONG_MESSAGE_FORMAT;
2740 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2741 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2743 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2744 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2745 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2747 w = fax_parms[4].length;
2750 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2751 for (i = 0; i < w; i++)
2752 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2753 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2754 len = (byte)(((T30_INFO *) 0)->station_id + 20);
2755 w = fax_parms[5].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[5].info[1+i];
2761 w = fax_parms[6].length;
2764 plci->fax_connect_info_buffer[len++] = (byte) w;
2765 for (i = 0; i < w; i++)
2766 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2767 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2768 & (1L << PRIVATE_FAX_NONSTANDARD))
2770 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2772 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2773 plci->fax_connect_info_buffer[len++] = 0;
2777 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2778 plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]);
2779 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2780 for (i = 0; i < fax_parms[7].length; i++)
2781 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2788 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2790 fax_info_change = TRUE;
2793 if (fax_control_bits != READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2795 WRITE_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2796 fax_info_change = TRUE;
2801 plci->fax_connect_info_length = len;
2802 if (fax_info_change)
2804 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2806 start_internal_command (Id, plci, fax_connect_info_command);
2811 start_internal_command (Id, plci, fax_adjust_b23_command);
2817 else Info = _WRONG_STATE;
2819 else Info = _WRONG_STATE;
2822 else if (plci->B3_prot == B3_RTP)
2824 plci->internal_req_buffer[0] = ncpi->length + 1;
2825 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2826 for (w = 0; w < ncpi->length; w++)
2827 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2828 start_internal_command (Id, plci, rtp_connect_b3_req_command);
2834 nl_req_ncci(plci,req,0);
2839 else Info = _WRONG_IDENTIFIER;
2842 _CONNECT_B3_R|CONFIRM,
2849 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2858 API_PARSE fax_parms[9];
2863 dbug(1,dprintf("connect_b3_res"));
2865 ncci = (word)(Id>>16);
2867 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2868 if (READ_WORD (&parms[0].info[0]) != 0)
2870 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2871 channel_request_xon (plci, a->ncci_ch[ncci]);
2872 channel_xmit_xon (plci);
2873 cleanup_ncci_data (plci, ncci);
2874 nl_req_ncci(plci,N_DISC,(byte)ncci);
2877 a->ncci_state[ncci] = INC_ACT_PENDING;
2879 req = N_CONNECT_ACK;
2881 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2885 & (1L << PRIVATE_FAX_NONSTANDARD))
2887 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2888 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2889 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2891 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2892 if (plci->fax_connect_info_length < len)
2894 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2895 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2897 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2899 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2903 if (plci->fax_connect_info_length <= len)
2904 plci->fax_connect_info_buffer[len] = 0;
2905 len += 1 + plci->fax_connect_info_buffer[len];
2906 if (plci->fax_connect_info_length <= len)
2907 plci->fax_connect_info_buffer[len] = 0;
2908 len += 1 + plci->fax_connect_info_buffer[len];
2909 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2910 plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]);
2911 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2912 for (i = 0; i < fax_parms[7].length; i++)
2913 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2915 plci->fax_connect_info_length = len;
2916 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2917 start_internal_command (Id, plci, fax_connect_ack_command);
2922 nl_req_ncci(plci,req,(byte)ncci);
2923 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2924 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2926 if (plci->B3_prot == 4)
2927 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2929 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2930 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2934 else if (plci->B3_prot == B3_RTP)
2936 plci->internal_req_buffer[0] = ncpi->length + 1;
2937 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2938 for (w = 0; w < ncpi->length; w++)
2939 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2940 start_internal_command (Id, plci, rtp_connect_b3_res_command);
2946 if(ncpi->length>2) {
2947 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2948 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2950 nl_req_ncci(plci,req,(byte)ncci);
2951 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2952 if (plci->adjust_b_restore)
2954 plci->adjust_b_restore = FALSE;
2955 start_internal_command (Id, plci, adjust_b_restore);
2964 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2968 ncci = (word)(Id>>16);
2969 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2971 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2972 && (plci->State != OUTG_DIS_PENDING))
2974 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2975 a->ncci_state[ncci] = CONNECTED;
2976 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2977 channel_request_xon (plci, a->ncci_ch[ncci]);
2978 channel_xmit_xon (plci);
2984 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
2990 dbug(1,dprintf("disconnect_b3_req"));
2992 Info = _WRONG_IDENTIFIER;
2993 ncci = (word)(Id>>16);
2996 Info = _WRONG_STATE;
2997 if ((a->ncci_state[ncci] == CONNECTED)
2998 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2999 || (a->ncci_state[ncci] == INC_CON_PENDING)
3000 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3002 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3003 channel_request_xon (plci, a->ncci_ch[ncci]);
3004 channel_xmit_xon (plci);
3006 if (a->ncci[ncci].data_pending
3007 && ((plci->B3_prot == B3_TRANSPARENT)
3008 || (plci->B3_prot == B3_T30)
3009 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3011 plci->send_disc = (byte)ncci;
3017 cleanup_ncci_data (plci, ncci);
3019 if(plci->B3_prot==2 || plci->B3_prot==3)
3024 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3027 nl_req_ncci(plci,N_DISC,(byte)ncci);
3033 _DISCONNECT_B3_R|CONFIRM,
3040 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3045 ncci = (word)(Id>>16);
3046 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3048 plci->requested_options_conn = 0;
3049 plci->fax_connect_info_length = 0;
3050 plci->ncpi_state = 0x00;
3051 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3052 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3054 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3056 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3057 if(i<MAX_CHANNELS_PER_PLCI) {
3058 if(plci->channels)plci->channels--;
3059 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3060 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3062 ncci_free_receive_buffers (plci, ncci);
3064 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3065 if(plci->State == SUSPENDING){
3070 "ws", (word)3, "\x03\x04\x00\x00");
3071 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3079 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3080 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3081 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3083 ncci_free_receive_buffers (plci, ncci);
3085 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3087 plci->adapter->ncci_state[ncci] = IDLE;
3088 start_internal_command (Id, plci, fax_disconnect_command);
3096 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3104 dbug(1,dprintf("data_b3_req"));
3106 Info = _WRONG_IDENTIFIER;
3107 ncci = (word)(Id>>16);
3108 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3112 Info = _WRONG_STATE;
3113 if ((a->ncci_state[ncci] == CONNECTED)
3114 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3117 ncci_ptr = &(a->ncci[ncci]);
3118 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3119 if (i >= MAX_DATA_B3)
3121 data = &(ncci_ptr->DBuffer[i]);
3122 data->Number = Number;
3123 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3124 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3127 data->P = (byte *)(*((dword *)(parms[0].info)));
3131 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3132 data->Length = READ_WORD(parms[1].info);
3133 data->Handle = READ_WORD(parms[2].info);
3134 data->Flags = READ_WORD(parms[3].info);
3135 (ncci_ptr->data_pending)++;
3137 /* check for delivery confirmation */
3138 if (data->Flags & 0x0004)
3140 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3141 if (i >= MAX_DATA_ACK)
3143 ncci_ptr->DataAck[i].Number = data->Number;
3144 ncci_ptr->DataAck[i].Handle = data->Handle;
3145 (ncci_ptr->data_ack_pending)++;
3156 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3157 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3160 TransmitBufferFree (appl, (byte *)(*((dword *)(parms[0].info))));
3168 "ww",READ_WORD(parms[2].info),Info);
3173 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3179 dbug(1,dprintf("data_b3_res"));
3181 ncci = (word)(Id>>16);
3183 n = READ_WORD(parms[0].info);
3184 dbug(1,dprintf("free(%d)",n));
3185 NCCIcode = ncci | (((word) a->Id) << 8);
3186 if(n<appl->MaxBuffer &&
3187 appl->DataNCCI[n]==NCCIcode &&
3188 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3189 dbug(1,dprintf("found"));
3190 appl->DataNCCI[n] = 0;
3192 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3193 channel_request_xon (plci, a->ncci_ch[ncci]);
3195 channel_xmit_xon (plci);
3197 if(appl->DataFlags[n] &4) {
3198 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3206 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3211 dbug(1,dprintf("reset_b3_req"));
3213 Info = _WRONG_IDENTIFIER;
3214 ncci = (word)(Id>>16);
3217 Info = _WRONG_STATE;
3218 switch (plci->B3_prot)
3222 if(a->ncci_state[ncci]==CONNECTED)
3224 nl_req_ncci(plci,N_RESET,(byte)ncci);
3229 case B3_TRANSPARENT:
3230 if(a->ncci_state[ncci]==CONNECTED)
3232 start_internal_command (Id, plci, reset_b3_command);
3238 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3240 _RESET_B3_R|CONFIRM,
3247 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3251 dbug(1,dprintf("reset_b3_res"));
3253 ncci = (word)(Id>>16);
3255 switch (plci->B3_prot)
3259 if(a->ncci_state[ncci]==INC_RES_PENDING)
3261 a->ncci_state[ncci] = CONNECTED;
3262 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3271 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3277 dbug(1,dprintf("connect_b3_t90_a_res"));
3279 ncci = (word)(Id>>16);
3281 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3282 a->ncci_state[ncci] = CONNECTED;
3284 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3285 a->ncci_state[ncci] = CONNECTED;
3287 req = N_CONNECT_ACK;
3289 /* parms[0]==0 for CAPI original message definition! */
3292 if(ncpi->length>2) {
3293 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3294 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3297 nl_req_ncci(plci,req,(byte)ncci);
3305 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3310 API_PARSE bp_parms[7];
3314 Info = _WRONG_IDENTIFIER;
3318 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3319 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3320 dbug(1,dprintf("PlciState=0x%x",plci->State));
3321 for(i=0;i<7;i++) bp_parms[i].length = 0;
3323 /* check if no channel is open, no B3 connected only */
3324 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3325 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3327 Info = _WRONG_STATE;
3329 /* check message format and fill bp_parms pointer */
3330 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3332 Info = _WRONG_MESSAGE_FORMAT;
3336 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3337 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3338 if(Id & EXT_CONTROLLER)
3340 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3343 plci->State=INC_CON_CONNECTED_ALERT;
3345 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3346 dump_c_ind_mask (plci);
3347 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3348 { /* its quasi a connect */
3349 if(test_c_ind_mask_bit (plci, i))
3350 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3354 api_save_msg(msg, "s", &plci->saved_msg);
3356 if(Id & EXT_CONTROLLER)
3358 if(tel) /* external controller in use by this PLCI */
3360 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3362 dbug(1,dprintf("Ext_Ctrl in use 1"));
3363 Info = _WRONG_STATE;
3366 else /* external controller NOT in use by this PLCI ? */
3368 if(a->AdvSignalPLCI)
3370 dbug(1,dprintf("Ext_Ctrl in use 2"));
3371 Info = _WRONG_STATE;
3373 else /* activate the codec */
3375 dbug(1,dprintf("Ext_Ctrl start"));
3376 if(AdvCodecSupport(a, plci, appl, 0) )
3378 dbug(1,dprintf("Error in codec procedures"));
3379 Info = _WRONG_STATE;
3381 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3383 plci->spoofed_msg = AWAITING_SELECT_B;
3384 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3386 dbug(1,dprintf("continue if codec loaded"));
3392 else /* external controller bit is OFF */
3394 if(tel) /* external controller in use, need to switch off */
3396 if(a->AdvSignalAppl==appl)
3398 CodecIdCheck(a, plci);
3401 dbug(1,dprintf("Ext_Ctrl disable"));
3405 dbug(1,dprintf("Ext_Ctrl not requested"));
3411 if (plci->call_dir & CALL_DIR_OUT)
3412 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3413 else if (plci->call_dir & CALL_DIR_IN)
3414 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3415 start_internal_command (Id, plci, select_b_command);
3420 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3424 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * parms)
3430 API_PARSE m_parms[5];
3435 static byte chi[2] = {0x01,0x00};
3436 static byte lli[2] = {0x01,0x00};
3437 static byte codec_cai[2] = {0x01,0x01};
3438 static byte null_msg = {0};
3439 static API_PARSE null_parms = { 0, &null_msg };
3443 dbug(1,dprintf("manufacturer_req"));
3444 for(i=0;i<5;i++) m_parms[i].length = 0;
3446 if(READ_DWORD(parms[0].info)!=_DI_MANU_ID) {
3447 Info = _WRONG_MESSAGE_FORMAT;
3449 command = READ_WORD(parms[1].info);
3454 case _DI_ASSIGN_PLCI:
3455 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3456 Info = _WRONG_MESSAGE_FORMAT;
3459 codec = READ_WORD(m_parms[0].info);
3460 ch = m_parms[1].info[0];
3461 dir = m_parms[2].info[0];
3462 if((i=get_plci(a))) {
3463 plci = &a->plci[i-1];
3465 plci->command = _MANUFACTURER_R;
3466 plci->m_command = command;
3467 plci->number = Number;
3468 plci->State = LOCAL_CONNECT;
3469 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3470 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3472 if((ch==1 || ch==2) && (dir<=2)) {
3473 chi[1] = (byte)(0x80|ch);
3475 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3479 Info = add_b1(plci,&m_parms[3],0,0);
3482 add_p(plci,CAI,codec_cai);
3484 /* manual 'swich on' to the codec support without signalling */
3485 /* first 'assign plci' with this function, then use */
3487 if(AdvCodecSupport(a, plci, appl, 0) ) {
3488 Info = _RESOURCE_ERROR;
3491 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3492 lli[1] = 0x10; /* local call codec stream */
3497 plci->State = LOCAL_CONNECT;
3498 plci->manufacturer = TRUE;
3499 plci->command = _MANUFACTURER_R;
3500 plci->m_command = command;
3501 plci->number = Number;
3505 add_p(plci,LLI,lli);
3506 add_p(plci,CHI,chi);
3507 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3508 sig_req(plci,ASSIGN,DSIG_ID);
3512 Info = add_b23(plci,&m_parms[3]);
3515 nl_req_ncci(plci,ASSIGN,0);
3521 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3522 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3524 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3525 plci->spoofed_msg = AWAITING_MANUF_CON;
3526 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3532 sig_req(plci,CALL_REQ,0);
3535 sig_req(plci,LISTEN_REQ,0);
3542 _MANUFACTURER_R|CONFIRM,
3545 "dww",_DI_MANU_ID,command,Info);
3551 else Info = _OUT_OF_PLCI;
3557 Info = _WRONG_IDENTIFIER;
3560 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3561 Info = _WRONG_MESSAGE_FORMAT;
3564 req = m_parms[0].info[0];
3565 plci->command = _MANUFACTURER_R;
3566 plci->m_command = command;
3567 plci->number = Number;
3570 plci->b_channel = getChannel(&m_parms[1]);
3571 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3572 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3574 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3575 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3580 else if(req==LAW_REQ)
3582 plci->cr_enquiry = TRUE;
3584 add_ss(plci,FTY,&m_parms[1]);
3585 sig_req(plci,req,0);
3589 if (plci->NL.Id && !plci->nl_remove_id)
3593 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3595 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3597 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3598 cleanup_ncci_data (plci, ncci);
3599 nl_req_ncci(plci,N_DISC,(byte)ncci);
3603 mixer_remove (plci);
3604 nl_req_ncci(plci,REMOVE,0);
3611 /* signalling control for loop activation B-channel */
3614 Info = _WRONG_IDENTIFIER;
3618 plci->command = _MANUFACTURER_R;
3619 plci->number = Number;
3621 sig_req(plci,SIG_CTRL,0);
3624 else Info = _WRONG_MESSAGE_FORMAT;
3628 /* activation control for receiver/transmitter B-channel */
3631 Info = _WRONG_IDENTIFIER;
3635 plci->command = _MANUFACTURER_R;
3636 plci->number = Number;
3638 sig_req(plci,DSP_CTRL,0);
3641 else Info = _WRONG_MESSAGE_FORMAT;
3646 /* TEL_CTRL commands to support non standard adjustments: */
3647 /* Ring on/off, Handset micro volume, external micro vol. */
3648 /* handset+external speaker volume, receiver+transm. gain,*/
3649 /* handsfree on (hookinfo off), set mixer command */
3651 if(command == _DI_ADV_CODEC)
3653 if(!a->AdvCodecPLCI) {
3654 Info = _WRONG_STATE;
3657 v_plci = a->AdvCodecPLCI;
3663 && (m->info[1] == 0x1c)
3664 && (m->info[2] >= 1))
3666 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3668 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3670 Info = _WRONG_STATE;
3673 a->adv_voice_coef_length = m->info[2] - 1;
3674 if (a->adv_voice_coef_length > m->length - 3)
3675 a->adv_voice_coef_length = (byte)(m->length - 3);
3676 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3677 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3678 for (i = 0; i < a->adv_voice_coef_length; i++)
3679 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3680 if (plci->B1_facilities & B1_FACILITY_VOICE)
3681 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3684 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3686 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3688 Info = _FACILITY_NOT_SUPPORTED;
3692 plci->dtmf_parameter_length = m->info[2] - 1;
3693 if (plci->dtmf_parameter_length > m->length - 3)
3694 plci->dtmf_parameter_length = (byte)(m->length - 3);
3695 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3696 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3697 for (i = 0; i < plci->dtmf_parameter_length; i++)
3698 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3699 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3700 dtmf_parameter_write (plci);
3710 Info = _WRONG_IDENTIFIER;
3714 add_ss(v_plci,FTY,m);
3715 sig_req(v_plci,TEL_CTRL,0);
3718 else Info = _WRONG_MESSAGE_FORMAT;
3722 case _DI_OPTIONS_REQUEST:
3723 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3724 Info = _WRONG_MESSAGE_FORMAT;
3727 if (READ_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3729 Info = _FACILITY_NOT_SUPPORTED;
3732 a->requested_options_table[appl->Id-1] = READ_DWORD (m_parms[0].info);
3738 Info = _WRONG_MESSAGE_FORMAT;
3744 _MANUFACTURER_R|CONFIRM,
3747 "dww",_DI_MANU_ID,command,Info);
3752 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
3756 API_PARSE m_parms[3];
3758 API_PARSE fax_parms[9];
3763 dbug(1,dprintf("manufacturer_res"));
3765 if ((msg[0].length == 0)
3766 || (msg[1].length == 0)
3767 || (READ_DWORD(msg[0].info)!=_DI_MANU_ID))
3771 indication = READ_WORD(msg[1].info);
3775 case _DI_NEGOTIATE_B3:
3778 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3779 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3781 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3784 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3786 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3790 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3791 if (plci->fax_connect_info_length < len)
3793 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3794 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3796 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3798 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3802 if (plci->fax_connect_info_length <= len)
3803 plci->fax_connect_info_buffer[len] = 0;
3804 len += 1 + plci->fax_connect_info_buffer[len];
3805 if (plci->fax_connect_info_length <= len)
3806 plci->fax_connect_info_buffer[len] = 0;
3807 len += 1 + plci->fax_connect_info_buffer[len];
3808 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3809 plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]);
3810 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3811 for (i = 0; i < fax_parms[7].length; i++)
3812 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3814 plci->fax_connect_info_length = len;
3815 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3816 start_internal_command (Id, plci, fax_edata_ack_command);
3823 /*------------------------------------------------------------------*/
3824 /* IDI callback function */
3825 /*------------------------------------------------------------------*/
3827 void callback(ENTITY * e)
3829 DIVA_CAPI_ADAPTER * a;
3840 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3841 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3843 a = &(adapter[(byte)e->user[0]]);
3844 plci = &(a->plci[e->user[1]]);
3845 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3848 If new protocol code and new XDI is used then CAPI should work
3849 fully in accordance with IDI cpec an look on callback field instead
3850 of Rc field for return codes.
3852 if (((e->complete == 0xff) && no_cancel_rc) ||
3853 (e->Rc && !no_cancel_rc)) {
3859 if (e->user[0] & 0x8000)
3862 If REMOVE request was sent then we have to wait until
3863 return code with Id set to zero arrives.
3864 All other return codes should be ignored.
3870 dbug(1,dprintf("cancel RC in REMOVE state"));
3873 channel_flow_control_remove (plci);
3874 for (i = 0; i < 256; i++)
3876 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3877 a->FlowControlIdTable[i] = 0;
3879 plci->nl_remove_id = 0;
3880 if (plci->rx_dma_descriptor > 0) {
3881 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3882 plci->rx_dma_descriptor = 0;
3887 a->FlowControlIdTable[ch] = e->Id;
3888 a->FlowControlSkipTable[ch] = 0;
3890 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3891 a->ch_flow_plci[ch] = plci->Id;
3897 Cancel return codes self, if feature was requested
3899 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3900 a->FlowControlIdTable[ch] = 0;
3901 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3902 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3907 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3909 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3917 control_rc (plci, 0, rc, ch, 0, TRUE);
3922 channel_x_on (plci, ch);
3923 if (plci->internal_command)
3924 control_rc (plci, req, rc, ch, 0, TRUE);
3928 if (plci->nl_global_req)
3930 global_req = plci->nl_global_req;
3931 plci->nl_global_req = 0;
3932 if (rc != ASSIGN_OK) {
3934 if (plci->rx_dma_descriptor > 0) {
3935 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3936 plci->rx_dma_descriptor = 0;
3939 channel_xmit_xon (plci);
3940 control_rc (plci, 0, rc, ch, global_req, TRUE);
3942 else if (plci->data_sent)
3944 channel_xmit_xon (plci);
3945 plci->data_sent = FALSE;
3948 if (plci->internal_command)
3949 control_rc (plci, req, rc, ch, 0, TRUE);
3953 channel_xmit_xon (plci);
3954 control_rc (plci, req, rc, ch, 0, TRUE);
3962 If REMOVE request was sent then we have to wait until
3963 return code with Id set to zero arrives.
3964 All other return codes should be ignored.
3970 dbug(1,dprintf("cancel RC in REMOVE state"));
3973 plci->sig_remove_id = 0;
3976 if (plci->sig_global_req)
3978 global_req = plci->sig_global_req;
3979 plci->sig_global_req = 0;
3980 if (rc != ASSIGN_OK)
3982 channel_xmit_xon (plci);
3983 control_rc (plci, 0, rc, ch, global_req, FALSE);
3987 channel_xmit_xon (plci);
3988 control_rc (plci, req, rc, ch, 0, FALSE);
3992 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3993 same callback. Also if new XDI and protocol code used then jump
3997 channel_xmit_xon(plci);
3998 goto capi_callback_suffix;
4002 channel_xmit_xon(plci);
4005 if (e->user[0] &0x8000) {
4006 byte Ind = e->Ind & 0x0f;
4008 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4009 (a->ch_flow_plci[Ch] == plci->Id)) {
4010 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4011 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4013 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4016 if ((e->RNR != 1) &&
4017 (a->ch_flow_plci[Ch] == plci->Id) &&
4018 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4019 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4020 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4028 capi_callback_suffix:
4030 while (!plci->req_in
4031 && !plci->internal_command
4032 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4034 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4036 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4038 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4039 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4040 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4041 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4042 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4044 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4045 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4049 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4051 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4053 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4054 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4056 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4058 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4059 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4061 i = api_put (appl, m);
4064 if (m->header.command == _DATA_B3_R)
4066 TransmitBufferFree (appl, (byte *)(m->info.data_b3_req.Data));
4068 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4072 if (plci->li_notify_update)
4074 plci->li_notify_update = FALSE;
4075 mixer_notify_update (plci, FALSE);
4084 void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4092 DIVA_CAPI_ADAPTER * a;
4095 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4096 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4099 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4102 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4103 if(plci->req_in!=plci->req_out)
4105 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4107 dbug(1,dprintf("req_1return"));
4110 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4112 plci->req_in = plci->req_in_start = plci->req_out = 0;
4113 dbug(1,dprintf("control_rc"));
4117 ncci = a->ch_ncci[ch];
4120 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4121 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4122 Number = plci->number;
4123 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));
4124 dbug(1,dprintf("channels=0x%x",plci->channels));
4125 if (plci_remove_check(plci))
4127 if(req==REMOVE && rc==ASSIGN_OK)
4129 sig_req(plci,HANGUP,0);
4130 sig_req(plci,REMOVE,0);
4135 switch(plci->command)
4138 dbug(1,dprintf("HoldRC=0x%x",rc));
4139 SSparms[1] = (byte)S_HOLD;
4142 plci->SuppState = IDLE;
4145 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4148 case C_RETRIEVE_REQ:
4149 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4150 SSparms[1] = (byte)S_RETRIEVE;
4153 plci->SuppState = CALL_HELD;
4156 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4160 dbug(1,dprintf("InfoRC=0x%x",rc));
4161 if(rc!=OK) Info=_WRONG_STATE;
4162 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4166 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4167 if (plci->State == INC_DIS_PENDING)
4169 if(plci->Sig.Id!=0xff)
4171 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4172 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4174 dbug(1,dprintf("No more IDs/Call_Req failed"));
4175 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4180 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4181 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4183 else /* D-ch activation */
4185 if (rc != ASSIGN_OK)
4187 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4188 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4193 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4194 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4195 plci->State = INC_ACT_PENDING;
4199 case _CONNECT_I|RESPONSE:
4200 if (plci->State != INC_DIS_PENDING)
4201 plci->State = INC_CON_ACCEPT;
4205 if (plci->State == INC_DIS_PENDING)
4207 if(plci->Sig.Id!=0xff)
4209 plci->State = OUTG_DIS_PENDING;
4210 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4223 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4226 ncci = get_ncci (plci, ch, 0);
4227 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4231 a->ncci_state[ncci] = INC_ACT_PENDING;
4232 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4233 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4237 a->ncci_state[ncci] = OUTG_CON_PENDING;
4238 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4242 case _CONNECT_B3_I|RESPONSE:
4246 /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4249 case _DISCONNECT_B3_R:
4250 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4253 case _MANUFACTURER_R:
4259 Info = _WRONG_IDENTIFIER;
4260 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4264 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4272 else if (plci->internal_command)
4274 switch(plci->internal_command)
4280 if(rc==OK) /* command supported, wait for indication */
4287 /* Get Supported Services */
4288 case GETSERV_REQ_PEND:
4289 if(rc==OK) /* command supported, wait for indication */
4293 WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4294 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4298 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4299 case INTERR_NUMBERS_REQ_PEND:
4300 case CF_START_PEND: /* Call Forwarding Start pending */
4301 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4302 case CCBS_REQUEST_REQ_PEND:
4303 case CCBS_DEACTIVATE_REQ_PEND:
4304 case CCBS_INTERROGATE_REQ_PEND:
4305 switch(plci->internal_command)
4307 case INTERR_DIVERSION_REQ_PEND:
4308 SSparms[1] = S_INTERROGATE_DIVERSION;
4310 case INTERR_NUMBERS_REQ_PEND:
4311 SSparms[1] = S_INTERROGATE_NUMBERS;
4314 SSparms[1] = S_CALL_FORWARDING_START;
4317 SSparms[1] = S_CALL_FORWARDING_STOP;
4319 case CCBS_REQUEST_REQ_PEND:
4320 SSparms[1] = S_CCBS_REQUEST;
4322 case CCBS_DEACTIVATE_REQ_PEND:
4323 SSparms[1] = S_CCBS_DEACTIVATE;
4325 case CCBS_INTERROGATE_REQ_PEND:
4326 SSparms[1] = S_CCBS_INTERROGATE;
4329 if(global_req==ASSIGN)
4331 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4334 if(!plci->appl) break;
4335 if(rc==ISDN_GUARD_REJ)
4337 Info = _CAPI_GUARD_ERROR;
4341 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4343 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4344 plci->number,"wws",Info,(word)3,SSparms);
4345 if(Info) plci_remove(plci);
4348 /* 3pty conference pending */
4350 if(!plci->relatedPTYPLCI) break;
4351 rplci = plci->relatedPTYPLCI;
4352 SSparms[1] = plci->ptyState;
4353 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4354 if(rplci->tel) rId|=EXT_CONTROLLER;
4357 Info = 0x300E; /* not supported */
4358 plci->relatedPTYPLCI = NULL;
4362 _FACILITY_R|CONFIRM,
4365 "wws",Info,(word)3,SSparms);
4368 /* Explicit Call Transfer pending */
4370 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4371 if(!plci->relatedPTYPLCI) break;
4372 rplci = plci->relatedPTYPLCI;
4374 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4375 if(rplci->tel) rId|=EXT_CONTROLLER;
4378 Info = 0x300E; /* not supported */
4379 plci->relatedPTYPLCI = NULL;
4383 _FACILITY_R|CONFIRM,
4386 "wws",Info,(word)3,SSparms);
4389 case _MANUFACTURER_R:
4390 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4391 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4393 dbug(1,dprintf("No more IDs"));
4394 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4395 plci_remove(plci); /* after codec init, internal codec commands pending */
4400 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4401 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4403 dbug(1,dprintf("No more IDs"));
4404 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4405 plci_remove(plci); /* after codec init, internal codec commands pending */
4409 case PERM_COD_HOOK: /* finished with Hook_Ind */
4413 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4414 plci->internal_command = PERM_COD_CONN_PEND;
4417 case PERM_COD_ASSIGN:
4418 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4419 if(rc!=ASSIGN_OK) break;
4420 sig_req(plci,CALL_REQ,0);
4422 plci->internal_command = PERM_COD_CALL;
4425 /* Null Call Reference Request pending */
4427 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4428 if(global_req==ASSIGN)
4436 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4437 appl->NullCREnable = FALSE;
4441 else if(req==NCR_FACILITY)
4445 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4449 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4450 appl->NullCREnable = FALSE;
4459 if(a->ncci_state[ncci]==CONNECTED)
4461 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4462 cleanup_ncci_data (plci, ncci);
4463 nl_req_ncci(plci,N_DISC,(byte)ncci);
4470 if (plci->State == INC_DIS_PENDING)
4472 sig_req(plci,CALL_REQ,0);
4474 plci->State=OUTG_CON_PENDING;
4478 case MWI_ACTIVATE_REQ_PEND:
4479 case MWI_DEACTIVATE_REQ_PEND:
4480 if(global_req == ASSIGN && rc==ASSIGN_OK)
4482 dbug(1,dprintf("MWI_REQ assigned"));
4489 Info = 0x2007; /* Illegal message parameter coding */
4490 dbug(1,dprintf("MWI_REQ invalid parameter"));
4494 Info = 0x300B; /* not supported */
4495 dbug(1,dprintf("MWI_REQ not supported"));
4497 /* 0x3010: Request not allowed in this state */
4498 WRITE_WORD(&SSparms[4],0x300E); /* SS not supported */
4501 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4503 WRITE_WORD(&SSparms[1],S_MWI_ACTIVATE);
4505 else WRITE_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4507 if(plci->cr_enquiry)
4510 _FACILITY_R|CONFIRM,
4513 "wws",Info,(word)3,SSparms);
4514 if(rc!=OK) plci_remove(plci);
4519 _FACILITY_R|CONFIRM,
4522 "wws",Info,(word)3,SSparms);
4526 case CONF_BEGIN_REQ_PEND:
4527 case CONF_ADD_REQ_PEND:
4528 case CONF_SPLIT_REQ_PEND:
4529 case CONF_DROP_REQ_PEND:
4530 case CONF_ISOLATE_REQ_PEND:
4531 case CONF_REATTACH_REQ_PEND:
4532 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4533 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4536 switch(plci->internal_command)
4538 case CONF_BEGIN_REQ_PEND:
4539 SSparms[1] = S_CONF_BEGIN;
4541 case CONF_ADD_REQ_PEND:
4542 SSparms[1] = S_CONF_ADD;
4543 rplci = plci->relatedPTYPLCI;
4544 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4546 case CONF_SPLIT_REQ_PEND:
4547 SSparms[1] = S_CONF_SPLIT;
4549 case CONF_DROP_REQ_PEND:
4550 SSparms[1] = S_CONF_DROP;
4552 case CONF_ISOLATE_REQ_PEND:
4553 SSparms[1] = S_CONF_ISOLATE;
4555 case CONF_REATTACH_REQ_PEND:
4556 SSparms[1] = S_CONF_REATTACH;
4562 Info = 0x300E; /* not supported */
4563 plci->relatedPTYPLCI = NULL;
4567 _FACILITY_R|CONFIRM,
4570 "wws",Info,(word)3,SSparms);
4573 case VSWITCH_REQ_PEND:
4576 if(plci->relatedPTYPLCI)
4578 plci->relatedPTYPLCI->vswitchstate=0;
4579 plci->relatedPTYPLCI->vsprot=0;
4580 plci->relatedPTYPLCI->vsprotdialect=0;
4582 plci->vswitchstate=0;
4584 plci->vsprotdialect=0;
4588 if(plci->relatedPTYPLCI &&
4589 plci->vswitchstate==1 &&
4590 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4591 plci->vswitchstate=3;
4595 /* Call Deflection Request pending (SSCT) */
4597 SSparms[1] = S_CALL_DEFLECTION;
4600 Info = 0x300E; /* not supported */
4601 plci->appl->CDEnable = 0;
4603 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4604 plci->number,"wws",Info,(word)3,SSparms);
4607 case RTP_CONNECT_B3_REQ_COMMAND_2:
4610 ncci = get_ncci (plci, ch, 0);
4611 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4613 a->ncci_state[ncci] = OUTG_CON_PENDING;
4617 if (plci->internal_command_queue[0])
4619 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4620 if (plci->internal_command)
4625 next_internal_command (Id, plci);
4630 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4631 if(plci->tel) Id|=EXT_CONTROLLER;
4633 switch(plci->internal_command)
4638 case START_L1_SIG_ASSIGN_PEND:
4639 case REM_L1_SIG_ASSIGN_PEND:
4640 if(global_req == ASSIGN)
4646 dbug(1,dprintf("***L1 Req rem PLCI"));
4647 plci->internal_command = 0;
4648 sig_req(plci,REMOVE,0);
4653 /* Call Deflection Request pending, just no appl ptr assigned */
4655 SSparms[1] = S_CALL_DEFLECTION;
4658 Info = 0x300E; /* not supported */
4660 for(i=0; i<max_appl; i++)
4662 if(application[i].CDEnable)
4664 if(!application[i].Id) application[i].CDEnable = 0;
4667 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4668 plci->number,"wws",Info,(word)3,SSparms);
4669 if(Info) application[i].CDEnable = 0;
4673 plci->internal_command = 0;
4676 case PERM_COD_HOOK: /* finished with Hook_Ind */
4680 plci->internal_command = PERM_COD_CONN_PEND;
4681 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4684 case PERM_COD_ASSIGN:
4685 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4686 plci->internal_command = 0;
4687 if(rc!=ASSIGN_OK) break;
4688 plci->internal_command = PERM_COD_CALL;
4689 sig_req(plci,CALL_REQ,0);
4693 case LISTEN_SIG_ASSIGN_PEND:
4696 plci->internal_command = 0;
4697 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4698 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4699 sig_req(plci,INDICATE_REQ,0);
4704 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4712 if(global_req == ASSIGN)
4716 sig_req(plci,LAW_REQ,0);
4718 dbug(1,dprintf("Auto-Law assigned"));
4722 dbug(1,dprintf("Auto-Law assign failed"));
4723 a->automatic_law = 3;
4724 plci->internal_command = 0;
4725 a->automatic_lawPLCI = NULL;
4729 else if(req == LAW_REQ && rc==OK)
4731 dbug(1,dprintf("Auto-Law initiated"));
4732 a->automatic_law = 2;
4733 plci->internal_command = 0;
4737 dbug(1,dprintf("Auto-Law not supported"));
4738 a->automatic_law = 3;
4739 plci->internal_command = 0;
4740 sig_req(plci,REMOVE,0);
4742 a->automatic_lawPLCI = NULL;
4746 plci_remove_check(plci);
4750 void data_rc(PLCI * plci, byte ch)
4753 DIVA_CAPI_ADAPTER * a;
4760 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4762 ncci = a->ch_ncci[ch];
4763 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4765 ncci_ptr = &(a->ncci[ncci]);
4766 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4767 if (ncci_ptr->data_pending)
4769 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4770 if (!(data->Flags &4) && a->ncci_state[ncci])
4772 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4773 if(plci->tel) Id|=EXT_CONTROLLER;
4774 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4775 "ww",data->Handle,0);
4777 (ncci_ptr->data_out)++;
4778 if (ncci_ptr->data_out == MAX_DATA_B3)
4779 ncci_ptr->data_out = 0;
4780 (ncci_ptr->data_pending)--;
4786 void data_ack(PLCI * plci, byte ch)
4789 DIVA_CAPI_ADAPTER * a;
4794 ncci = a->ch_ncci[ch];
4795 ncci_ptr = &(a->ncci[ncci]);
4796 if (ncci_ptr->data_ack_pending)
4798 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4800 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4801 if(plci->tel) Id|=EXT_CONTROLLER;
4802 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4803 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4805 (ncci_ptr->data_ack_out)++;
4806 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4807 ncci_ptr->data_ack_out = 0;
4808 (ncci_ptr->data_ack_pending)--;
4812 void sig_ind(PLCI * plci)
4822 DIVA_CAPI_ADAPTER * a;
4823 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4824 #define MAXPARMSIDS 31
4825 byte * parms[MAXPARMSIDS];
4827 byte * multi_fac_parms[MAX_MULTI_IE];
4828 byte * multi_pi_parms [MAX_MULTI_IE];
4829 byte * multi_ssext_parms [MAX_MULTI_IE];
4830 byte * multi_CiPN_parms [MAX_MULTI_IE];
4832 byte * multi_vswitch_parms [MAX_MULTI_IE];
4839 byte *esc_profile = "";
4842 PLCI * tplci = NULL;
4843 byte chi[] = "\x02\x18\x01";
4844 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4845 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4846 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4847 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4848 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4849 /* (see Info_Mask Bit 4, first IE. then the message type) */
4851 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4852 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4853 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4854 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4855 /* 14 FTY repl by ESC_CHI */
4856 /* 18 PI repl by ESC_LAW */
4857 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4858 word multi_fac_id[] = {1, FTY};
4859 word multi_pi_id[] = {1, PI};
4860 word multi_CiPN_id[] = {1, OAD};
4861 word multi_ssext_id[] = {1, ESC_SSEXT};
4863 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4867 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4868 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4869 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4870 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4871 byte force_mt_info = FALSE;
4877 Id = ((word)plci->Id<<8)|a->Id;
4878 WRITE_WORD(&SS_Ind[4],0x0000);
4880 if (plci->sig_remove_id)
4882 plci->Sig.RNR = 2; /* discard */
4883 dbug(1,dprintf("SIG discard while remove pending"));
4886 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4887 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4888 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4889 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4894 if(plci->Sig.Ind==HANGUP && plci->channels)
4897 plci->hangup_flow_ctrl_timer++;
4898 /* recover the network layer after timeout */
4899 if(plci->hangup_flow_ctrl_timer==100)
4901 dbug(1,dprintf("Exceptional disc"));
4903 plci->hangup_flow_ctrl_timer = 0;
4904 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4906 if (a->ncci_plci[ncci] == plci->Id)
4908 cleanup_ncci_data (plci, ncci);
4909 if(plci->channels)plci->channels--;
4911 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4915 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4922 /* do first parse the info with no OAD in, because OAD will be converted */
4923 /* first the multiple facility IE, then mult. progress ind. */
4924 /* then the parameters for the info_ind + conn_ind */
4925 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4926 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4927 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4929 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4931 IndParse(plci,parms_id,parms,0);
4932 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4933 esc_chi = parms[14];
4934 esc_law = parms[18];
4935 pty_cai = parms[24];
4937 esc_profile = parms[27];
4938 if(esc_cr[0] && plci)
4940 if(plci->cr_enquiry && plci->appl)
4942 plci->cr_enquiry = FALSE;
4945 /* b = total length */
4946 /* b = indication type */
4947 /* b = length of all IEs */
4949 /* S = IE1 length + cont. */
4951 /* S = IE2 lenght + cont. */
4956 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4957 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);
4960 /* create the additional info structure */
4961 add_i[1] = parms[15]; /* KEY of additional info */
4962 add_i[2] = parms[11]; /* UUI of additional info */
4963 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4965 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4966 /* indication returns by the card if requested by the function */
4967 /* AutomaticLaw() after driver init */
4968 if (a->automatic_law<4)
4972 dbug(0,dprintf("u-Law selected"));
4976 dbug(0,dprintf("a-Law selected"));
4979 a->automatic_law = 4;
4980 if(plci==a->automatic_lawPLCI) {
4981 plci->internal_command = 0;
4982 sig_req(plci,REMOVE,0);
4984 a->automatic_lawPLCI = NULL;
4989 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4990 UnMapController (a->Id), READ_DWORD (&esc_profile[6]),
4991 READ_DWORD (&esc_profile[10]), READ_DWORD (&esc_profile[14]),
4992 READ_DWORD (&esc_profile[18]), READ_DWORD (&esc_profile[46])));
4994 a->profile.Global_Options &= 0x000000ffL;
4995 a->profile.B1_Protocols &= 0x000003ffL;
4996 a->profile.B2_Protocols &= 0x00001fdfL;
4997 a->profile.B3_Protocols &= 0x000000b7L;
4999 a->profile.Global_Options &= READ_DWORD (&esc_profile[6]) |
5000 GL_BCHANNEL_OPERATION_SUPPORTED;
5001 a->profile.B1_Protocols &= READ_DWORD (&esc_profile[10]);
5002 a->profile.B2_Protocols &= READ_DWORD (&esc_profile[14]);
5003 a->profile.B3_Protocols &= READ_DWORD (&esc_profile[18]);
5004 a->manufacturer_features = READ_DWORD (&esc_profile[46]);
5005 a->man_profile.private_options = 0;
5007 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5009 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5010 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5014 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5015 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5016 a->man_profile.rtp_primary_payloads = READ_DWORD (&esc_profile[50]);
5017 a->man_profile.rtp_additional_payloads = READ_DWORD (&esc_profile[54]);
5020 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5021 a->man_profile.private_options |= 1L << PRIVATE_T38;
5024 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5025 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5028 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5029 a->man_profile.private_options |= 1L << PRIVATE_V18;
5032 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5033 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5036 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5037 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5040 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5041 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5044 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5045 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5048 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5049 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5054 a->profile.Global_Options &= 0x0000007fL;
5055 a->profile.B1_Protocols &= 0x000003dfL;
5056 a->profile.B2_Protocols &= 0x00001adfL;
5057 a->profile.B3_Protocols &= 0x000000b7L;
5058 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5060 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5061 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5063 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5065 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5066 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5067 UnMapController (a->Id), a->profile.Global_Options,
5068 a->profile.B1_Protocols, a->profile.B2_Protocols,
5069 a->profile.B3_Protocols, a->manufacturer_features));
5071 /* codec plci for the handset/hook state support is just an internal id */
5072 if(plci!=a->AdvCodecPLCI)
5074 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5075 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5076 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5077 SendInfo(plci,Id, parms, force_mt_info);
5079 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5083 /* switch the codec to the b-channel */
5084 if(esc_chi[0] && plci && !plci->SuppState){
5085 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5086 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5087 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5088 if(plci->tel==ADV_VOICE && plci->appl) {
5089 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5093 if(plci->appl) Number = plci->appl->Number++;
5095 switch(plci->Sig.Ind) {
5096 /* Response to Get_Supported_Services request */
5098 dbug(1,dprintf("S_Supported"));
5099 if(!plci->appl) break;
5102 WRITE_DWORD(&CF_Ind[6],READ_DWORD(&pty_cai[1]) );
5106 WRITE_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5108 WRITE_WORD (&CF_Ind[1], 0);
5109 WRITE_WORD (&CF_Ind[4], 0);
5110 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5114 /* Supplementary Service rejected */
5116 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5117 if(!pty_cai[0]) break;
5122 case THREE_PTY_BEGIN:
5123 if(!plci->relatedPTYPLCI) break;
5124 tplci = plci->relatedPTYPLCI;
5125 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5126 if(tplci->tel) rId|=EXT_CONTROLLER;
5127 if(pty_cai[5]==ECT_EXECUTE)
5129 WRITE_WORD(&SS_Ind[1],S_ECT);
5131 plci->vswitchstate=0;
5132 plci->relatedPTYPLCI->vswitchstate=0;
5137 WRITE_WORD(&SS_Ind[1],pty_cai[5]+3);
5139 if(pty_cai[2]!=0xff)
5141 WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5145 WRITE_WORD(&SS_Ind[4],0x300E);
5147 plci->relatedPTYPLCI = NULL;
5149 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5152 case CALL_DEFLECTION:
5153 if(pty_cai[2]!=0xff)
5155 WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5159 WRITE_WORD(&SS_Ind[4],0x300E);
5161 WRITE_WORD(&SS_Ind[1],pty_cai[5]);
5162 for(i=0; i<max_appl; i++)
5164 if(application[i].CDEnable)
5166 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5167 application[i].CDEnable = FALSE;
5172 case DEACTIVATION_DIVERSION:
5173 case ACTIVATION_DIVERSION:
5174 case DIVERSION_INTERROGATE_CFU:
5175 case DIVERSION_INTERROGATE_CFB:
5176 case DIVERSION_INTERROGATE_CFNR:
5177 case DIVERSION_INTERROGATE_NUM:
5179 case CCBS_DEACTIVATE:
5180 case CCBS_INTERROGATE:
5181 if(!plci->appl) break;
5182 if(pty_cai[2]!=0xff)
5184 WRITE_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5188 WRITE_WORD(&Interr_Err_Ind[4],0x300E);
5192 case DEACTIVATION_DIVERSION:
5193 dbug(1,dprintf("Deact_Div"));
5194 Interr_Err_Ind[0]=0x9;
5195 Interr_Err_Ind[3]=0x6;
5196 WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5198 case ACTIVATION_DIVERSION:
5199 dbug(1,dprintf("Act_Div"));
5200 Interr_Err_Ind[0]=0x9;
5201 Interr_Err_Ind[3]=0x6;
5202 WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5204 case DIVERSION_INTERROGATE_CFU:
5205 case DIVERSION_INTERROGATE_CFB:
5206 case DIVERSION_INTERROGATE_CFNR:
5207 dbug(1,dprintf("Interr_Div"));
5208 Interr_Err_Ind[0]=0xa;
5209 Interr_Err_Ind[3]=0x7;
5210 WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5212 case DIVERSION_INTERROGATE_NUM:
5213 dbug(1,dprintf("Interr_Num"));
5214 Interr_Err_Ind[0]=0xa;
5215 Interr_Err_Ind[3]=0x7;
5216 WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5219 dbug(1,dprintf("CCBS Request"));
5220 Interr_Err_Ind[0]=0xd;
5221 Interr_Err_Ind[3]=0xa;
5222 WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5224 case CCBS_DEACTIVATE:
5225 dbug(1,dprintf("CCBS Deactivate"));
5226 Interr_Err_Ind[0]=0x9;
5227 Interr_Err_Ind[3]=0x6;
5228 WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5230 case CCBS_INTERROGATE:
5231 dbug(1,dprintf("CCBS Interrogate"));
5232 Interr_Err_Ind[0]=0xb;
5233 Interr_Err_Ind[3]=0x8;
5234 WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5237 WRITE_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5238 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5241 case ACTIVATION_MWI:
5242 case DEACTIVATION_MWI:
5243 if(pty_cai[5]==ACTIVATION_MWI)
5245 WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5247 else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5249 if(pty_cai[2]!=0xff)
5251 WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5255 WRITE_WORD(&SS_Ind[4],0x300E);
5258 if(plci->cr_enquiry)
5260 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5265 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5268 case CONF_ADD: /* ERROR */
5278 WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5284 WRITE_WORD(&CONF_Ind[1],S_CONF_DROP);
5285 plci->ptyState = CONNECTED;
5290 WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5291 plci->ptyState = CONNECTED;
5296 WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5297 plci->ptyState = CONNECTED;
5300 WRITE_WORD(&CONF_Ind[1],S_CONF_ADD);
5301 plci->relatedPTYPLCI = NULL;
5302 tplci=plci->relatedPTYPLCI;
5303 if(tplci) tplci->ptyState = CONNECTED;
5304 plci->ptyState = CONNECTED;
5308 if(pty_cai[2]!=0xff)
5310 WRITE_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5314 WRITE_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5315 within the required time */
5318 WRITE_DWORD(&CONF_Ind[6],0x0);
5319 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5324 /* Supplementary Service indicates success */
5326 dbug(1,dprintf("Service_Ind"));
5327 WRITE_WORD (&CF_Ind[4], 0);
5331 case THREE_PTY_BEGIN:
5333 if(!plci->relatedPTYPLCI) break;
5334 tplci = plci->relatedPTYPLCI;
5335 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5336 if(tplci->tel) rId|=EXT_CONTROLLER;
5337 if(pty_cai[5]==ECT_EXECUTE)
5339 WRITE_WORD(&SS_Ind[1],S_ECT);
5341 if(plci->vswitchstate!=3)
5344 plci->ptyState = IDLE;
5345 plci->relatedPTYPLCI = NULL;
5350 dbug(1,dprintf("ECT OK"));
5351 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5358 switch (plci->ptyState)
5361 plci->ptyState = CONNECTED;
5362 dbug(1,dprintf("3PTY ON"));
5366 plci->ptyState = IDLE;
5367 plci->relatedPTYPLCI = NULL;
5369 dbug(1,dprintf("3PTY OFF"));
5372 WRITE_WORD(&SS_Ind[1],pty_cai[5]+3);
5373 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5377 case CALL_DEFLECTION:
5378 WRITE_WORD(&SS_Ind[1],pty_cai[5]);
5379 for(i=0; i<max_appl; i++)
5381 if(application[i].CDEnable)
5383 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5384 application[i].CDEnable = FALSE;
5389 case DEACTIVATION_DIVERSION:
5390 case ACTIVATION_DIVERSION:
5391 if(!plci->appl) break;
5392 WRITE_WORD(&CF_Ind[1],pty_cai[5]+2);
5393 WRITE_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5394 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5398 case DIVERSION_INTERROGATE_CFU:
5399 case DIVERSION_INTERROGATE_CFB:
5400 case DIVERSION_INTERROGATE_CFNR:
5401 case DIVERSION_INTERROGATE_NUM:
5403 case CCBS_DEACTIVATE:
5404 case CCBS_INTERROGATE:
5405 if(!plci->appl) break;
5408 case DIVERSION_INTERROGATE_CFU:
5409 case DIVERSION_INTERROGATE_CFB:
5410 case DIVERSION_INTERROGATE_CFNR:
5411 dbug(1,dprintf("Interr_Div"));
5412 WRITE_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5413 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5415 case DIVERSION_INTERROGATE_NUM:
5416 dbug(1,dprintf("Interr_Num"));
5417 WRITE_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5418 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5421 dbug(1,dprintf("CCBS Request"));
5422 WRITE_WORD(&pty_cai[1],S_CCBS_REQUEST);
5423 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5425 case CCBS_DEACTIVATE:
5426 dbug(1,dprintf("CCBS Deactivate"));
5427 WRITE_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5428 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5430 case CCBS_INTERROGATE:
5431 dbug(1,dprintf("CCBS Interrogate"));
5432 WRITE_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5433 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5436 WRITE_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5437 WRITE_DWORD(&pty_cai[6],plci->appl->S_Handle);
5438 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5442 case ACTIVATION_MWI:
5443 case DEACTIVATION_MWI:
5444 if(pty_cai[5]==ACTIVATION_MWI)
5446 WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5448 else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5449 if(plci->cr_enquiry)
5451 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5456 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5459 case MWI_INDICATION:
5460 if(pty_cai[0]>=0x12)
5462 WRITE_WORD(&pty_cai[3],S_MWI_INDICATE);
5463 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5464 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5465 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5467 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5469 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5473 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5478 for(i=0; i<max_appl; i++)
5480 if(a->Notification_Mask[i]&SMASK_MWI)
5482 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5490 facility[2]= 0; /* returncode */
5492 else facility[2]= 0xff;
5497 facility[2]= 0xff; /* returncode */
5500 facility[1]= MWI_RESPONSE; /* Function */
5501 add_p(plci,CAI,facility);
5502 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5503 sig_req(plci,S_SERVICE,0);
5506 next_internal_command (Id, plci);
5508 case CONF_ADD: /* OK */
5513 case CONF_PARTYDISC:
5519 WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5523 WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */
5527 WRITE_DWORD(&CONF_Ind[6],0x0);
5531 WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5536 WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5541 WRITE_WORD(&CONF_Ind[1],S_CONF_DROP);
5546 WRITE_WORD(&CONF_Ind[1],S_CONF_ADD);
5548 WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */
5549 tplci=plci->relatedPTYPLCI;
5550 if(tplci) tplci->ptyState = CONNECTED;
5552 case CONF_PARTYDISC:
5555 WRITE_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5557 WRITE_DWORD(&CONF_Ind[4],d); /* PartyID */
5560 plci->ptyState = CONNECTED;
5561 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5563 case CCBS_INFO_RETAIN:
5564 case CCBS_ERASECALLLINKAGEID:
5565 case CCBS_STOP_ALERTING:
5570 case CCBS_INFO_RETAIN:
5571 WRITE_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5573 case CCBS_STOP_ALERTING:
5574 WRITE_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5576 case CCBS_ERASECALLLINKAGEID:
5577 WRITE_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5585 WRITE_WORD(&CONF_Ind[4],w); /* PartyID */
5587 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5589 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5593 for(i=0; i<max_appl; i++)
5594 if(a->Notification_Mask[i]&SMASK_CCBS)
5595 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5604 i = _L3_CAUSE | cau[2];
5605 if(cau[2]==0) i = 0x3603;
5611 WRITE_WORD(&SS_Ind[1],S_HOLD);
5612 WRITE_WORD(&SS_Ind[4],i);
5613 if(plci->SuppState == HOLD_REQUEST)
5615 plci->SuppState = IDLE;
5616 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5621 if(plci->SuppState == HOLD_REQUEST)
5623 plci->SuppState = CALL_HELD;
5624 CodecIdCheck(a, plci);
5625 start_internal_command (Id, plci, hold_save_command);
5629 case CALL_RETRIEVE_REJ:
5633 i = _L3_CAUSE | cau[2];
5634 if(cau[2]==0) i = 0x3603;
5640 WRITE_WORD(&SS_Ind[1],S_RETRIEVE);
5641 WRITE_WORD(&SS_Ind[4],i);
5642 if(plci->SuppState == RETRIEVE_REQUEST)
5644 plci->SuppState = CALL_HELD;
5645 CodecIdCheck(a, plci);
5646 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5650 case CALL_RETRIEVE_ACK:
5651 WRITE_WORD(&SS_Ind[1],S_RETRIEVE);
5652 if(plci->SuppState == RETRIEVE_REQUEST)
5654 plci->SuppState = IDLE;
5655 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5656 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5659 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5660 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5661 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5662 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5664 dbug(1,dprintf("Get B-ch"));
5665 start_internal_command (Id, plci, retrieve_restore_command);
5668 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5671 start_internal_command (Id, plci, retrieve_restore_command);
5676 if(plci->State != LISTENING) {
5677 sig_req(plci,HANGUP,0);
5681 cip = find_cip(a,parms[4],parms[6]);
5683 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5684 clear_c_ind_mask (plci);
5685 if (!remove_started && !a->adapter_disabled)
5687 set_c_ind_mask_bit (plci, MAX_APPL);
5688 group_optimization(a, plci);
5689 for(i=0; i<max_appl; i++) {
5690 if(application[i].Id
5691 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5692 && CPN_filter_ok(parms[0],a,i)
5693 && test_group_ind_mask_bit (plci, i) ) {
5694 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5695 set_c_ind_mask_bit (plci, i);
5696 dump_c_ind_mask (plci);
5697 plci->State = INC_CON_PENDING;
5698 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5699 CALL_DIR_IN | CALL_DIR_ANSWER;
5701 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5702 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5704 /* if a listen on the ext controller is done, check if hook states */
5705 /* are supported or if just a on board codec must be activated */
5706 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5707 if(a->profile.Global_Options & HANDSET)
5708 plci->tel = ADV_VOICE;
5709 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5711 if(plci->tel) Id|=EXT_CONTROLLER;
5712 a->codec_listen[i] = plci;
5715 sendf(&application[i],_CONNECT_I,Id,0,
5716 "wSSSSSSSbSSSSS", cip, /* CIP */
5717 parms[0], /* CalledPartyNumber */
5718 multi_CiPN_parms[0], /* CallingPartyNumber */
5719 parms[2], /* CalledPartySubad */
5720 parms[3], /* CallingPartySubad */
5721 parms[4], /* BearerCapability */
5722 parms[5], /* LowLC */
5723 parms[6], /* HighLC */
5724 ai_len, /* nested struct add_i */
5725 add_i[0], /* B channel info */
5726 add_i[1], /* keypad facility */
5727 add_i[2], /* user user data */
5728 add_i[3], /* nested facility */
5729 multi_CiPN_parms[1] /* second CiPN(SCR) */
5731 SendSSExtInd(&application[i],
5735 SendSetupInfo(&application[i],
5739 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE));
5742 clear_c_ind_mask_bit (plci, MAX_APPL);
5743 dump_c_ind_mask (plci);
5745 if(c_ind_mask_empty (plci)) {
5746 sig_req(plci,HANGUP,0);
5750 plci->notifiedcall = 0;
5755 case CALL_PEND_NOTIFY:
5756 plci->notifiedcall = 1;
5762 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5764 if(plci->internal_command==PERM_COD_CONN_PEND)
5766 if(plci->State==ADVANCED_VOICE_NOSIG)
5768 dbug(1,dprintf("***Codec OK"));
5769 if(a->AdvSignalPLCI)
5771 tplci = a->AdvSignalPLCI;
5772 if(tplci->spoofed_msg)
5774 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5776 tplci->internal_command = 0;
5777 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5778 switch (tplci->spoofed_msg)
5781 tplci->command = _CONNECT_I|RESPONSE;
5782 api_load_msg (&tplci->saved_msg, saved_parms);
5783 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5784 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5786 /* early B3 connect (CIP mask bit 9) no release after a disc */
5787 add_p(tplci,LLI,"\x01\x01");
5789 add_s(tplci, CONN_NR, &saved_parms[2]);
5790 add_s(tplci, LLC, &saved_parms[4]);
5791 add_ai(tplci, &saved_parms[5]);
5792 tplci->State = INC_CON_ACCEPT;
5793 sig_req(tplci, CALL_RES,0);
5797 case AWAITING_SELECT_B:
5798 dbug(1,dprintf("Select_B continue"));
5799 start_internal_command (x_Id, tplci, select_b_command);
5802 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5805 dbug(1,dprintf("No SigID!"));
5806 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5810 tplci->command = _MANUFACTURER_R;
5811 api_load_msg (&tplci->saved_msg, saved_parms);
5812 dir = saved_parms[2].info[0];
5814 sig_req(tplci,CALL_REQ,0);
5817 sig_req(tplci,LISTEN_REQ,0);
5820 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5823 case (CALL_REQ|AWAITING_MANUF_CON):
5824 sig_req(tplci,CALL_REQ,0);
5831 dbug(1,dprintf("No SigID!"));
5832 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5836 tplci->command = _CONNECT_R;
5837 api_load_msg (&tplci->saved_msg, saved_parms);
5838 add_s(tplci,CPN,&saved_parms[1]);
5839 add_s(tplci,DSA,&saved_parms[3]);
5840 add_ai(tplci,&saved_parms[9]);
5841 sig_req(tplci,CALL_REQ,0);
5846 tplci->command = C_RETRIEVE_REQ;
5847 sig_req(tplci,CALL_RETRIEVE,0);
5851 tplci->spoofed_msg = 0;
5852 if (tplci->internal_command == 0)
5853 next_internal_command (x_Id, tplci);
5856 next_internal_command (Id, plci);
5859 dbug(1,dprintf("***Codec Hook Init Req"));
5860 plci->internal_command = PERM_COD_HOOK;
5861 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5862 sig_req(plci,TEL_CTRL,0);
5866 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5867 && plci->State!=INC_ACT_PENDING)
5869 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5870 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5872 chi[2] = plci->b_channel;
5873 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5875 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5876 plci->State = INC_ACT_PENDING;
5882 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5883 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5884 switch (ie[1]&0x91) {
5885 case 0x80: /* hook off */
5887 if(plci->internal_command==PERM_COD_HOOK)
5889 dbug(1,dprintf("init:hook_off"));
5890 plci->hook_state = ie[1];
5891 next_internal_command (Id, plci);
5894 else /* ignore doubled hook indications */
5896 if( ((plci->hook_state)&0xf0)==0x80)
5898 dbug(1,dprintf("ignore hook"));
5901 plci->hook_state = ie[1]&0x91;
5903 /* check for incoming call pending */
5904 /* and signal '+'.Appl must decide */
5905 /* with connect_res if call must */
5906 /* accepted or not */
5907 for(i=0, tplci=NULL;i<max_appl;i++){
5908 if(a->codec_listen[i]
5909 && (a->codec_listen[i]->State==INC_CON_PENDING
5910 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5911 tplci = a->codec_listen[i];
5912 tplci->appl = &application[i];
5915 /* no incoming call, do outgoing call */
5916 /* and signal '+' if outg. setup */
5917 if(!a->AdvSignalPLCI && !tplci){
5918 if((i=get_plci(a))) {
5919 a->AdvSignalPLCI = &a->plci[i-1];
5920 tplci = a->AdvSignalPLCI;
5921 tplci->tel = ADV_VOICE;
5922 WRITE_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5923 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5924 /* early B3 connect (CIP mask bit 9) no release after a disc */
5925 add_p(tplci,LLI,"\x01\x01");
5927 add_p(tplci, CAI, voice_cai);
5928 add_p(tplci, OAD, a->TelOAD);
5929 add_p(tplci, OSA, a->TelOSA);
5930 add_p(tplci,SHIFT|6,NULL);
5931 add_p(tplci,SIN,"\x02\x01\x00");
5932 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5933 sig_req(tplci,ASSIGN,DSIG_ID);
5934 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5935 a->AdvSignalPLCI->command = 0;
5936 tplci->appl = a->AdvSignalAppl;
5937 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5944 Id = ((word)tplci->Id<<8)|a->Id;
5950 "ws", (word)0, "\x01+");
5953 case 0x90: /* hook on */
5955 if(plci->internal_command==PERM_COD_HOOK)
5957 dbug(1,dprintf("init:hook_on"));
5958 plci->hook_state = ie[1]&0x91;
5959 next_internal_command (Id, plci);
5962 else /* ignore doubled hook indications */
5964 if( ((plci->hook_state)&0xf0)==0x90) break;
5965 plci->hook_state = ie[1]&0x91;
5967 /* hangup the adv. voice call and signal '-' to the appl */
5968 if(a->AdvSignalPLCI) {
5969 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5970 if(plci->tel) Id|=EXT_CONTROLLER;
5971 sendf(a->AdvSignalAppl,
5975 "ws", (word)0, "\x01-");
5976 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5977 a->AdvSignalPLCI->command = 0;
5978 sig_req(a->AdvSignalPLCI,HANGUP,0);
5979 send_req(a->AdvSignalPLCI);
5987 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5988 WRITE_WORD(&resume_cau[4],GOOD);
5989 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5993 clear_c_ind_mask (plci);
5995 if (plci->NL.Id && !plci->nl_remove_id) {
5996 mixer_remove (plci);
5997 nl_req_ncci(plci,REMOVE,0);
5999 if (!plci->sig_remove_id) {
6000 plci->internal_command = 0;
6001 sig_req(plci,REMOVE,0);
6004 if(!plci->channels) {
6005 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6006 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6014 plci->hangup_flow_ctrl_timer=0;
6015 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6018 i = _L3_CAUSE | cau[2];
6019 if(cau[2]==0) i = 0;
6020 else if(cau[2]==8) i = _L1_ERROR;
6021 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6022 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6028 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6030 for(i=0; i<max_appl; i++)
6032 if(test_c_ind_mask_bit (plci, i))
6033 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6038 clear_c_ind_mask (plci);
6042 if (plci->State == LISTENING)
6044 plci->notifiedcall=0;
6047 plci->State = INC_DIS_PENDING;
6048 if(c_ind_mask_empty (plci))
6051 if (plci->NL.Id && !plci->nl_remove_id)
6053 mixer_remove (plci);
6054 nl_req_ncci(plci,REMOVE,0);
6056 if (!plci->sig_remove_id)
6058 plci->internal_command = 0;
6059 sig_req(plci,REMOVE,0);
6066 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6067 /* result in a second HANGUP! Don't generate another */
6069 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6071 if(plci->State==RESUMING)
6073 WRITE_WORD(&resume_cau[4],i);
6074 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6076 plci->State = INC_DIS_PENDING;
6077 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6083 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6087 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6090 if(plci->relatedPTYPLCI &&
6091 plci->vswitchstate==3 &&
6092 plci->relatedPTYPLCI->vswitchstate==3 &&
6093 parms[MAXPARMSIDS-1][0])
6095 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6096 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6097 send_req(plci->relatedPTYPLCI);
6099 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6106 static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6111 byte * Info_Element;
6114 dbug(1,dprintf("SetupInfo"));
6116 for(i=0; i<MAXPARMSIDS; i++) {
6123 dbug(1,dprintf("CPN "));
6124 Info_Number = 0x0070;
6126 Info_Sent_Flag = TRUE;
6128 case 8: /* display */
6129 dbug(1,dprintf("display(%d)",i));
6130 Info_Number = 0x0028;
6132 Info_Sent_Flag = TRUE;
6134 case 16: /* Channel Id */
6135 dbug(1,dprintf("CHI"));
6136 Info_Number = 0x0018;
6138 Info_Sent_Flag = TRUE;
6139 mixer_set_bchannel_id (plci, Info_Element);
6141 case 19: /* Redirected Number */
6142 dbug(1,dprintf("RDN"));
6143 Info_Number = 0x0074;
6145 Info_Sent_Flag = TRUE;
6147 case 20: /* Redirected Number extended */
6148 dbug(1,dprintf("RDX"));
6149 Info_Number = 0x0073;
6151 Info_Sent_Flag = TRUE;
6153 case 22: /* Redirecing Number */
6154 dbug(1,dprintf("RIN"));
6155 Info_Number = 0x0076;
6157 Info_Sent_Flag = TRUE;
6165 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6166 Info_Number = 0x8000 |5;
6171 if(Info_Sent_Flag && Info_Number){
6172 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6173 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6180 void SendInfo(PLCI * plci, dword Id, byte * * parms, byte iesent)
6187 byte * Info_Element;
6189 static byte charges[5] = {4,0,0,0,0};
6190 static byte cause[] = {0x02,0x80,0x00};
6193 dbug(1,dprintf("InfoParse "));
6198 && plci->Sig.Ind!=NCR_FACILITY
6201 dbug(1,dprintf("NoParse "));
6205 for(i=0; i<MAXPARMSIDS; i++) {
6212 dbug(1,dprintf("CPN "));
6213 Info_Number = 0x0070;
6216 case 7: /* ESC_CAU */
6217 dbug(1,dprintf("cau(0x%x)",ie[2]));
6218 Info_Number = 0x0008;
6221 Info_Element = NULL;
6223 case 8: /* display */
6224 dbug(1,dprintf("display(%d)",i));
6225 Info_Number = 0x0028;
6228 case 9: /* Date display */
6229 dbug(1,dprintf("date(%d)",i));
6230 Info_Number = 0x0029;
6233 case 10: /* charges */
6234 for(j=0;j<4;j++) charges[1+j] = 0;
6235 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6236 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6237 Info_Number = 0x4000;
6239 Info_Element = charges;
6241 case 11: /* user user info */
6242 dbug(1,dprintf("uui"));
6243 Info_Number = 0x007E;
6246 case 12: /* congestion receiver ready */
6247 dbug(1,dprintf("clRDY"));
6248 Info_Number = 0x00B0;
6252 case 13: /* congestion receiver not ready */
6253 dbug(1,dprintf("clNRDY"));
6254 Info_Number = 0x00BF;
6258 case 15: /* Keypad Facility */
6259 dbug(1,dprintf("KEY"));
6260 Info_Number = 0x002C;
6263 case 16: /* Channel Id */
6264 dbug(1,dprintf("CHI"));
6265 Info_Number = 0x0018;
6267 mixer_set_bchannel_id (plci, Info_Element);
6269 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6270 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6271 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6272 Info_Number = 0x0008;
6274 if(cause[2] != ie[2]) Info_Element = cause;
6276 case 19: /* Redirected Number */
6277 dbug(1,dprintf("RDN"));
6278 Info_Number = 0x0074;
6281 case 22: /* Redirecing Number */
6282 dbug(1,dprintf("RIN"));
6283 Info_Number = 0x0076;
6286 case 23: /* Notification Indicator */
6287 dbug(1,dprintf("NI"));
6288 Info_Number = (word)NI;
6291 case 26: /* Call State */
6292 dbug(1,dprintf("CST"));
6293 Info_Number = (word)CST;
6294 Info_Mask = 0x01; /* do with cause i.e. for now */
6296 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6297 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6298 Info_Number = 0x8000 |ie[3];
6299 if(iesent) Info_Mask = 0xffff;
6300 else Info_Mask = 0x10;
6311 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6313 for(j=0; j<max_appl; j++)
6315 appl = &application[j];
6318 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6320 dbug(1,dprintf("NCR_Ind"));
6322 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6326 else if(!plci->appl)
6327 { /* overlap receiving broadcast */
6332 || Info_Number==UUI )
6334 for(j=0; j<max_appl; j++)
6336 if(test_c_ind_mask_bit (plci, j))
6338 dbug(1,dprintf("Ovl_Ind"));
6340 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6344 } /* all other signalling states */
6346 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6348 dbug(1,dprintf("Std_Ind"));
6350 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6356 byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse)
6362 byte * Info_Element;
6370 && plci->Sig.Ind!=NCR_FACILITY
6374 dbug(1,dprintf("NoM-IEParse "));
6377 dbug(1,dprintf("M-IEParse "));
6379 for(i=0; i<MAX_MULTI_IE; i++)
6386 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6387 Info_Number = (word)ie_type;
6388 Info_Mask = (word)info_mask;
6391 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6393 for(j=0; j<max_appl; j++)
6395 appl = &application[j];
6398 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6401 dbug(1,dprintf("Mlt_NCR_Ind"));
6402 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6406 else if(!plci->appl && Info_Number)
6407 { /* overlap receiving broadcast */
6408 for(j=0; j<max_appl; j++)
6410 if(test_c_ind_mask_bit (plci, j))
6413 dbug(1,dprintf("Mlt_Ovl_Ind"));
6414 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6417 } /* all other signalling states */
6419 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6422 dbug(1,dprintf("Mlt_Std_Ind"));
6423 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6429 void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6432 /* Format of multi_ssext_parms[i][]:
6435 2 byte SSEXT_REQ/SSEXT_IND
6443 && plci->Sig.Ind!=NCR_FACILITY
6445 for(i=0;i<MAX_MULTI_IE;i++)
6447 if(parms[i][0]<6) continue;
6448 if(parms[i][2]==SSEXT_REQ) continue;
6452 parms[i][0]=0; /* kill it */
6453 sendf(appl,_MANUFACTURER_I,
6463 parms[i][0]=0; /* kill it */
6464 sendf(plci->appl,_MANUFACTURER_I,
6475 void nl_ind(PLCI * plci)
6480 DIVA_CAPI_ADAPTER * a;
6486 byte len, ncci_state;
6489 word fax_feature_bits;
6490 byte fax_send_edata_ack;
6491 static byte v120_header_buffer[2 + 3];
6492 static word fax_info[] = {
6493 0, /* T30_SUCCESS */
6494 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6495 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6496 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6497 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6498 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6499 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6500 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6501 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6502 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6503 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6504 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6505 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6506 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6507 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6508 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6509 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6510 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6511 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6512 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6513 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6514 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6518 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6519 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6520 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6521 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6522 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6523 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6524 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6525 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6526 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6527 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6528 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6530 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6531 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6532 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6533 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6537 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6538 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6539 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6542 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6545 static word rtp_info[] = {
6546 GOOD, /* RTP_SUCCESS */
6547 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6550 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6552 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6553 0x00000000, 0x00000000, 0x00000000, 0x00000000
6556 ch = plci->NL.IndCh;
6558 ncci = a->ch_ncci[ch];
6559 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6560 if(plci->tel) Id|=EXT_CONTROLLER;
6561 APPLptr = plci->appl;
6562 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",
6563 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6565 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6567 if (plci->nl_remove_id)
6569 plci->NL.RNR = 2; /* discard */
6570 dbug(1,dprintf("NL discard while remove pending"));
6573 if((plci->NL.Ind &0x0f)==N_CONNECT)
6575 if(plci->State==INC_DIS_PENDING
6576 || plci->State==OUTG_DIS_PENDING
6577 || plci->State==IDLE)
6579 plci->NL.RNR = 2; /* discard */
6580 dbug(1,dprintf("discard n_connect"));
6583 if(plci->State < INC_ACT_PENDING)
6585 plci->NL.RNR = 1; /* flow control */
6586 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6591 if(!APPLptr) /* no application or invalid data */
6592 { /* while reloading the DSP */
6593 dbug(1,dprintf("discard1"));
6598 if (((plci->NL.Ind &0x0f) == N_UDATA)
6599 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6600 || (plci->B2_prot == 7)
6601 || (plci->B3_prot == 7)) )
6603 plci->ncpi_buffer[0] = 0;
6605 ncpi_state = plci->ncpi_state;
6606 if (plci->NL.complete == 1)
6608 byte * data = &plci->NL.RBuffer->P[0];
6610 if ((plci->NL.RBuffer->length >= 12)
6611 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6612 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6614 word conn_opt, ncpi_opt = 0x00;
6615 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6617 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6618 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6619 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6620 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6622 data++; /* indication code */
6623 data += 2; /* timestamp */
6624 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6625 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6626 data++; /* connected norm */
6627 conn_opt = READ_WORD(data);
6628 data += 2; /* connected options */
6630 WRITE_WORD (&(plci->ncpi_buffer[1]), (word)(READ_DWORD(data) & 0x0000FFFF));
6632 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6634 ncpi_opt |= MDM_NCPI_ECM_V42;
6636 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6638 ncpi_opt |= MDM_NCPI_ECM_MNP;
6642 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6644 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6646 ncpi_opt |= MDM_NCPI_COMPRESSED;
6648 WRITE_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6649 plci->ncpi_buffer[0] = 4;
6651 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6654 if (plci->B3_prot == 7)
6656 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6657 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6658 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6660 a->ncci_state[ncci] = INC_ACT_PENDING;
6661 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6662 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6666 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6667 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6668 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6669 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6677 if(plci->NL.complete == 2)
6679 if (((plci->NL.Ind &0x0f) == N_UDATA)
6680 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6682 switch(plci->RData[0].P[0])
6685 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6686 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6687 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6689 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6690 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6691 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6693 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6694 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6696 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6697 dtmf_confirmation (Id, plci);
6701 case UDATA_INDICATION_MIXER_TAP_DATA:
6702 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6703 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6706 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6707 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6712 case UDATA_INDICATION_MIXER_COEFS_SET:
6713 mixer_indication_coefs_set (Id, plci);
6715 case UDATA_INDICATION_XCONNECT_FROM:
6716 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6718 case UDATA_INDICATION_XCONNECT_TO:
6719 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6723 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6724 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6735 if ((plci->RData[0].PLength != 0)
6736 && ((plci->B2_prot == B2_V120_ASYNC)
6737 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6738 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6741 sendf(plci->appl,_DATA_B3_I,Id,0,
6744 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6752 sendf(plci->appl,_DATA_B3_I,Id,0,
6755 plci->RData[0].PLength,
6764 fax_feature_bits = 0;
6765 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6766 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6767 (plci->NL.Ind &0x0f)==N_DISC ||
6768 (plci->NL.Ind &0x0f)==N_EDATA ||
6769 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6772 plci->ncpi_buffer[0] = 0;
6773 switch (plci->B3_prot) {
6776 break; /* no network control protocol info - jfr */
6779 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6780 plci->ncpi_buffer[0] = (byte)(i+3);
6781 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6782 plci->ncpi_buffer[2] = 0;
6783 plci->ncpi_buffer[3] = 0;
6785 case 4: /*T.30 - FAX*/
6786 case 5: /*T.30 - FAX*/
6787 if(plci->NL.RLength>=sizeof(T30_INFO))
6789 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6791 WRITE_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6792 fax_feature_bits = READ_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6793 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6794 if (plci->B3_prot == 5)
6796 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6797 i |= 0x8000; /* This is not an ECM connection */
6798 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6799 i |= 0x4000; /* This is a connection with MMR compression */
6800 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6801 i |= 0x2000; /* This is a connection with MR compression */
6802 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6803 i |= 0x0004; /* More documents */
6804 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6805 i |= 0x0002; /* Fax-polling indication */
6807 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6808 WRITE_WORD(&(plci->ncpi_buffer[3]),i);
6809 WRITE_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6810 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6811 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6812 plci->ncpi_buffer[len] = 0;
6813 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6815 plci->ncpi_buffer[len] = 20;
6816 for (i = 0; i < 20; i++)
6817 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6819 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6821 if (((T30_INFO *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
6822 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6824 info = _FAX_PROTOCOL_ERROR;
6827 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6828 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6830 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6831 while (i < plci->NL.RBuffer->length)
6832 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6835 plci->ncpi_buffer[0] = len;
6836 fax_feature_bits = READ_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6837 WRITE_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6839 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6840 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6841 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6842 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6843 || (((plci->NL.Ind &0x0f) == N_EDATA)
6844 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6845 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6846 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6848 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6850 if (((plci->NL.Ind &0x0f) == N_DISC)
6851 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6852 || (((plci->NL.Ind &0x0f) == N_EDATA)
6853 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6855 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6861 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6863 if (plci->NL.RLength != 0)
6865 info = rtp_info[plci->NL.RBuffer->P[0]];
6866 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6867 for (i = 1; i < plci->NL.RLength; i++)
6868 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6876 switch(plci->NL.Ind &0x0f) {
6878 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6880 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6881 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6882 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6884 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6885 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6886 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6887 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6888 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6889 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6891 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6892 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6893 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6894 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6895 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6896 fax_send_edata_ack = FALSE;
6899 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6901 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6904 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6905 && !(READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6906 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6907 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6909 a->ncci_state[ncci] = INC_ACT_PENDING;
6910 if (plci->B3_prot == 4)
6911 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6913 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6914 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6918 case EDATA_T30_TRAIN_OK:
6919 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6920 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6921 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6923 if (plci->B3_prot == 4)
6924 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6926 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6927 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6931 case EDATA_T30_EOP_CAPI:
6932 if (a->ncci_state[ncci] == CONNECTED)
6934 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6935 a->ncci_state[ncci] = INC_DIS_PENDING;
6936 plci->ncpi_state = 0;
6937 fax_send_edata_ack = FALSE;
6944 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6946 case EDATA_T30_TRAIN_OK:
6947 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6948 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6949 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6951 if (plci->B3_prot == 4)
6952 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6954 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6955 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6960 if (fax_send_edata_ack)
6962 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6963 plci->fax_edata_ack_length = 1;
6964 start_internal_command (Id, plci, fax_edata_ack_command);
6969 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6973 if (!a->ch_ncci[ch])
6975 ncci = get_ncci (plci, ch, 0);
6976 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6978 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6979 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6981 msg = _CONNECT_B3_I;
6982 if (a->ncci_state[ncci] == IDLE)
6984 else if (plci->B3_prot == 1)
6985 msg = _CONNECT_B3_T90_ACTIVE_I;
6987 a->ncci_state[ncci] = INC_CON_PENDING;
6988 if(plci->B3_prot == 4)
6989 sendf(plci->appl,msg,Id,0,"s","");
6991 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6994 dbug(1,dprintf("N_connect_Ack"));
6995 if (plci->internal_command_queue[0]
6996 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6997 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6998 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7000 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7001 if (!plci->internal_command)
7002 next_internal_command (Id, plci);
7005 msg = _CONNECT_B3_ACTIVE_I;
7006 if (plci->B3_prot == 1)
7008 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7009 msg = _CONNECT_B3_T90_ACTIVE_I;
7010 a->ncci_state[ncci] = INC_ACT_PENDING;
7011 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7013 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7015 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7016 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7017 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7019 a->ncci_state[ncci] = INC_ACT_PENDING;
7020 if (plci->B3_prot == 4)
7021 sendf(plci->appl,msg,Id,0,"s","");
7023 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7024 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7029 a->ncci_state[ncci] = INC_ACT_PENDING;
7030 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7032 if (plci->adjust_b_restore)
7034 plci->adjust_b_restore = FALSE;
7035 start_internal_command (Id, plci, adjust_b_restore);
7040 if (plci->internal_command_queue[0]
7041 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7042 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7043 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7045 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7046 if (!plci->internal_command)
7047 next_internal_command (Id, plci);
7049 ncci_state = a->ncci_state[ncci];
7050 ncci_remove (plci, ncci, FALSE);
7052 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7053 /* channel, so we cannot store the state in ncci_state! The */
7054 /* information which channel we received a N_DISC is thus */
7055 /* stored in the inc_dis_ncci_table buffer. */
7056 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7057 plci->inc_dis_ncci_table[i] = (byte) ncci;
7059 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7061 && (plci->B1_resource == 16)
7062 && (plci->State <= CONNECTED))
7065 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7066 WRITE_WORD (&plci->ncpi_buffer[1], i);
7067 WRITE_WORD (&plci->ncpi_buffer[3], 0);
7068 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7069 WRITE_WORD (&plci->ncpi_buffer[5], i);
7070 WRITE_WORD (&plci->ncpi_buffer[7], 0);
7071 plci->ncpi_buffer[len] = 0;
7072 plci->ncpi_buffer[0] = len;
7073 if(plci->B3_prot == 4)
7074 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7078 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7079 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7081 plci->ncpi_buffer[++len] = 0;
7082 plci->ncpi_buffer[++len] = 0;
7083 plci->ncpi_buffer[++len] = 0;
7084 plci->ncpi_buffer[0] = len;
7087 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7089 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7090 plci->ncpi_state = 0;
7091 sig_req(plci,HANGUP,0);
7093 plci->State = OUTG_DIS_PENDING;
7096 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7097 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7098 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7100 if (ncci_state == IDLE)
7104 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7105 if(plci->State == SUSPENDING){
7110 "ws", (word)3, "\x03\x04\x00\x00");
7111 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7118 else if (plci->channels)
7120 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7121 plci->ncpi_state = 0;
7122 if ((ncci_state == OUTG_REJ_PENDING)
7123 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7125 sig_req(plci,HANGUP,0);
7127 plci->State = OUTG_DIS_PENDING;
7132 a->ncci_state[ncci] = INC_RES_PENDING;
7133 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7136 a->ncci_state[ncci] = CONNECTED;
7137 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7141 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7143 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
7144 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7145 plci->NL.R = plci->RData;
7151 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7152 || (a->ncci_state[ncci] == IDLE)
7153 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7158 if ((a->ncci_state[ncci] != CONNECTED)
7159 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7160 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7162 dbug(1,dprintf("flow control"));
7163 plci->NL.RNR = 1; /* flow control */
7164 channel_x_off (plci, ch, 0);
7168 NCCIcode = ncci | (((word)a->Id) << 8);
7170 /* count all buffers within the Application pool */
7171 /* belonging to the same NCCI. If this is below the */
7172 /* number of buffers available per NCCI we accept */
7173 /* this packet, otherwise we reject it */
7176 for(i=0; i<APPLptr->MaxBuffer; i++) {
7177 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7178 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7181 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7183 dbug(3,dprintf("Flow-Control"));
7185 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7186 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7189 dbug(3,dprintf("DiscardData"));
7191 channel_x_off (plci, ch, 0);
7197 APPLptr->NCCIDataFlowCtrlTimer = 0;
7200 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7201 if(!plci->RData[0].P) {
7203 channel_x_off (plci, ch, 0);
7207 APPLptr->DataNCCI[Num] = NCCIcode;
7208 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7209 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7212 plci->RFlags = plci->NL.Ind>>4;
7213 plci->RData[0].PLength = APPLptr->MaxDataLength;
7214 plci->NL.R = plci->RData;
7215 if ((plci->NL.RLength != 0)
7216 && ((plci->B2_prot == B2_V120_ASYNC)
7217 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7218 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7220 plci->RData[1].P = plci->RData[0].P;
7221 plci->RData[1].PLength = plci->RData[0].PLength;
7222 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7223 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7224 plci->RData[0].PLength = 1;
7226 plci->RData[0].PLength = 2;
7227 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7228 plci->RFlags |= 0x0010;
7229 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7230 plci->RFlags |= 0x8000;
7235 if((plci->NL.Ind &0x0f)==N_UDATA)
7236 plci->RFlags |= 0x0010;
7238 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7239 plci->RFlags |= 0x0001;
7245 data_ack (plci, ch);
7253 /*------------------------------------------------------------------*/
7254 /* find a free PLCI */
7255 /*------------------------------------------------------------------*/
7257 word get_plci(DIVA_CAPI_ADAPTER * a)
7263 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7264 if(i==a->max_plci) {
7265 dbug(1,dprintf("get_plci: out of PLCIs"));
7269 plci->Id = (byte)(i+1);
7277 plci->relatedPTYPLCI = NULL;
7279 plci->SuppState = IDLE;
7282 plci->B1_resource = 0;
7287 plci->m_command = 0;
7288 init_internal_command_queue (plci);
7290 plci->req_in_start = 0;
7293 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7294 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7295 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7297 plci->data_sent = FALSE;
7298 plci->send_disc = 0;
7299 plci->sig_global_req = 0;
7300 plci->sig_remove_id = 0;
7301 plci->nl_global_req = 0;
7302 plci->nl_remove_id = 0;
7304 plci->manufacturer = FALSE;
7305 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7306 plci->spoofed_msg = 0;
7308 plci->cr_enquiry = FALSE;
7309 plci->hangup_flow_ctrl_timer = 0;
7311 plci->ncci_ring_list = 0;
7312 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7313 clear_c_ind_mask (plci);
7314 set_group_ind_mask (plci);
7315 plci->fax_connect_info_length = 0;
7316 plci->nsf_control_bits = 0;
7317 plci->ncpi_state = 0x00;
7318 plci->ncpi_buffer[0] = 0;
7320 plci->requested_options_conn = 0;
7321 plci->requested_options = 0;
7322 plci->notifiedcall = 0;
7323 plci->vswitchstate = 0;
7325 plci->vsprotdialect = 0;
7326 init_b1_config (plci);
7327 dbug(1,dprintf("get_plci(%x)",plci->Id));
7331 /*------------------------------------------------------------------*/
7332 /* put a parameter in the parameter buffer */
7333 /*------------------------------------------------------------------*/
7335 static void add_p(PLCI * plci, byte code, byte * p)
7340 if(p) p_length = p[0];
7341 add_ie(plci, code, p, p_length);
7344 /*------------------------------------------------------------------*/
7345 /* put a structure in the parameter buffer */
7346 /*------------------------------------------------------------------*/
7347 static void add_s(PLCI * plci, byte code, API_PARSE * p)
7349 if(p) add_ie(plci, code, p->info, (word)p->length);
7352 /*------------------------------------------------------------------*/
7353 /* put multiple structures in the parameter buffer */
7354 /*------------------------------------------------------------------*/
7355 static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7360 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7361 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7362 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7363 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7368 /*------------------------------------------------------------------*/
7369 /* return the channel number sent by the application in a esc_chi */
7370 /*------------------------------------------------------------------*/
7371 static byte getChannel(API_PARSE * p)
7376 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7378 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7386 /*------------------------------------------------------------------*/
7387 /* put an information element in the parameter buffer */
7388 /*------------------------------------------------------------------*/
7390 static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7394 if(!(code &0x80) && !p_length) return;
7396 if(plci->req_in==plci->req_in_start) {
7402 plci->RBuffer[plci->req_in++] = code;
7405 plci->RBuffer[plci->req_in++] = (byte)p_length;
7406 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7409 plci->RBuffer[plci->req_in++] = 0;
7412 /*------------------------------------------------------------------*/
7413 /* put a unstructured data into the buffer */
7414 /*------------------------------------------------------------------*/
7416 void add_d(PLCI * plci, word length, byte * p)
7420 if(plci->req_in==plci->req_in_start) {
7426 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7429 /*------------------------------------------------------------------*/
7430 /* put parameters from the Additional Info parameter in the */
7431 /* parameter buffer */
7432 /*------------------------------------------------------------------*/
7434 void add_ai(PLCI * plci, API_PARSE * ai)
7437 API_PARSE ai_parms[5];
7439 for(i=0;i<5;i++) ai_parms[i].length = 0;
7443 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7446 add_s (plci,KEY,&ai_parms[1]);
7447 add_s (plci,UUI,&ai_parms[2]);
7448 add_ss(plci,FTY,&ai_parms[3]);
7451 /*------------------------------------------------------------------*/
7452 /* put parameter for b1 protocol in the parameter buffer */
7453 /*------------------------------------------------------------------*/
7455 word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7457 API_PARSE bp_parms[8];
7458 API_PARSE mdm_cfg[9];
7459 API_PARSE global_config[2];
7461 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7462 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7465 API_PARSE mdm_cfg_v18[4];
7470 for(i=0;i<8;i++) bp_parms[i].length = 0;
7471 for(i=0;i<2;i++) global_config[i].length = 0;
7473 dbug(1,dprintf("add_b1"));
7474 api_save_msg(bp, "s", &plci->B_protocol);
7476 if(b_channel_info==2){
7477 plci->B1_resource = 0;
7478 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7479 add_p(plci, CAI, "\x01\x00");
7480 dbug(1,dprintf("Cai=1,0 (no resource)"));
7484 if(plci->tel == CODEC_PERMANENT) return 0;
7485 else if(plci->tel == CODEC){
7486 plci->B1_resource = 1;
7487 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7488 add_p(plci, CAI, "\x01\x01");
7489 dbug(1,dprintf("Cai=1,1 (Codec)"));
7492 else if(plci->tel == ADV_VOICE){
7493 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7494 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7495 voice_cai[1] = plci->B1_resource;
7496 WRITE_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7497 add_p(plci, CAI, voice_cai);
7498 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7501 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7502 if (plci->call_dir & CALL_DIR_OUT)
7503 plci->call_dir |= CALL_DIR_ORIGINATE;
7504 else if (plci->call_dir & CALL_DIR_IN)
7505 plci->call_dir |= CALL_DIR_ANSWER;
7508 plci->B1_resource = 0x5;
7509 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7510 add_p(plci, CAI, "\x01\x05");
7514 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7515 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7516 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7518 bp_parms[6].length = 0;
7519 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7521 dbug(1,dprintf("b-form.!"));
7522 return _WRONG_MESSAGE_FORMAT;
7525 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7527 dbug(1,dprintf("b-form.!"));
7528 return _WRONG_MESSAGE_FORMAT;
7531 if(bp_parms[6].length)
7533 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7535 return _WRONG_MESSAGE_FORMAT;
7537 switch(READ_WORD(global_config[0].info))
7540 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7543 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7547 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7550 if ((READ_WORD(bp_parms[0].info) == B1_RTP)
7551 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7553 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7554 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7555 cai[1] = plci->B1_resource;
7559 WRITE_WORD(&cai[5],plci->appl->MaxDataLength);
7560 for (i = 0; i < bp_parms[3].length; i++)
7561 cai[7+i] = bp_parms[3].info[1+i];
7562 cai[0] = 6 + bp_parms[3].length;
7563 add_p(plci, CAI, cai);
7568 if ((READ_WORD(bp_parms[0].info) == B1_PIAFS)
7569 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7571 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7572 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7573 cai[1] = plci->B1_resource;
7577 WRITE_WORD(&cai[5],plci->appl->MaxDataLength);
7579 add_p(plci, CAI, cai);
7584 if ((READ_WORD(bp_parms[0].info) >= 32)
7585 || (!((1L << READ_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7586 && ((READ_WORD(bp_parms[0].info) != 3)
7587 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7588 || ((bp_parms[3].length != 0) && (READ_WORD(&bp_parms[3].info[1]) != 0) && (READ_WORD(&bp_parms[3].info[1]) != 56000)))))
7590 return _B1_NOT_SUPPORTED;
7592 plci->B1_resource = add_b1_facilities (plci, resource[READ_WORD(bp_parms[0].info)],
7593 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7594 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7596 cai[1] = plci->B1_resource;
7597 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7599 if ((READ_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7600 || (READ_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7601 || (READ_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7603 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7605 if (bp_parms[3].length)
7607 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7609 return (_WRONG_MESSAGE_FORMAT);
7612 cai[2] = 0; /* Bit rate for adaptation */
7614 dbug(1,dprintf("MDM Max Bit Rate:<%d>", READ_WORD(mdm_cfg[0].info)));
7616 WRITE_WORD (&cai[13], 0); /* Min Tx speed */
7617 WRITE_WORD (&cai[15], READ_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7618 WRITE_WORD (&cai[17], 0); /* Min Rx speed */
7619 WRITE_WORD (&cai[19], READ_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7621 cai[3] = 0; /* Async framing parameters */
7622 switch (READ_WORD (mdm_cfg[2].info))
7624 case 1: /* odd parity */
7625 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7626 dbug(1,dprintf("MDM: odd parity"));
7629 case 2: /* even parity */
7630 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7631 dbug(1,dprintf("MDM: even parity"));
7635 dbug(1,dprintf("MDM: no parity"));
7639 switch (READ_WORD (mdm_cfg[3].info))
7641 case 1: /* 2 stop bits */
7642 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7643 dbug(1,dprintf("MDM: 2 stop bits"));
7647 dbug(1,dprintf("MDM: 1 stop bit"));
7651 switch (READ_WORD (mdm_cfg[1].info))
7654 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7655 dbug(1,dprintf("MDM: 5 bits"));
7659 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7660 dbug(1,dprintf("MDM: 6 bits"));
7664 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7665 dbug(1,dprintf("MDM: 7 bits"));
7669 dbug(1,dprintf("MDM: 8 bits"));
7673 cai[7] = 0; /* Line taking options */
7674 cai[8] = 0; /* Modulation negotiation options */
7675 cai[9] = 0; /* Modulation options */
7677 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7679 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7680 dbug(1, dprintf("MDM: Reverse direction"));
7683 if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7685 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7686 dbug(1, dprintf("MDM: Disable retrain"));
7689 if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7691 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7692 dbug(1, dprintf("MDM: Disable ring tone"));
7695 if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7697 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7698 dbug(1, dprintf("MDM: 1800 guard tone"));
7700 else if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7702 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7703 dbug(1, dprintf("MDM: 550 guard tone"));
7706 if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7708 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7709 dbug(1, dprintf("MDM: V100"));
7711 else if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7713 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7714 dbug(1, dprintf("MDM: IN CLASS"));
7716 else if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7718 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7719 dbug(1, dprintf("MDM: DISABLED"));
7723 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7724 && (READ_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7726 plci->requested_options |= 1L << PRIVATE_V18;
7728 if (READ_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7729 plci->requested_options |= 1L << PRIVATE_VOWN;
7731 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7732 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7734 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7737 if (mdm_cfg[6].length >= 4)
7739 d = READ_DWORD(&mdm_cfg[6].info[1]);
7740 cai[7] |= (byte) d; /* line taking options */
7741 cai[9] |= (byte)(d >> 8); /* modulation options */
7742 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7743 cai[++i] = (byte)(d >> 24);
7744 if (mdm_cfg[6].length >= 8)
7746 d = READ_DWORD(&mdm_cfg[6].info[5]);
7747 cai[10] |= (byte) d; /* disabled modulations mask */
7748 cai[11] |= (byte)(d >> 8);
7749 if (mdm_cfg[6].length >= 12)
7751 d = READ_DWORD(&mdm_cfg[6].info[9]);
7752 cai[12] = (byte) d; /* enabled modulations mask */
7753 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7754 cai[++i] = (byte)(d >> 16);
7755 cai[++i] = (byte)(d >> 24);
7757 if (mdm_cfg[6].length >= 14)
7759 w = READ_WORD(&mdm_cfg[6].info[13]);
7761 WRITE_WORD(&cai[13], w); /* min tx speed */
7762 if (mdm_cfg[6].length >= 16)
7764 w = READ_WORD(&mdm_cfg[6].info[15]);
7766 WRITE_WORD(&cai[15], w); /* max tx speed */
7767 if (mdm_cfg[6].length >= 18)
7769 w = READ_WORD(&mdm_cfg[6].info[17]);
7771 WRITE_WORD(&cai[17], w); /* min rx speed */
7772 if (mdm_cfg[6].length >= 20)
7774 w = READ_WORD(&mdm_cfg[6].info[19]);
7776 WRITE_WORD(&cai[19], w); /* max rx speed */
7777 if (mdm_cfg[6].length >= 22)
7779 w = READ_WORD(&mdm_cfg[6].info[21]);
7780 cai[23] = (byte)(-((short) w)); /* transmit level */
7781 if (mdm_cfg[6].length >= 24)
7783 w = READ_WORD(&mdm_cfg[6].info[23]);
7784 cai[22] |= (byte) w; /* info options mask */
7785 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7797 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7799 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7801 for (n = 0; n < 3; n++)
7803 cai[i] = (byte)(mdm_cfg_v18[n].length);
7804 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7805 cai[i+j] = mdm_cfg_v18[n].info[j];
7810 cai[0] = (byte)(i - 1);
7816 if(READ_WORD(bp_parms[0].info)==2 || /* V.110 async */
7817 READ_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7819 if(bp_parms[3].length){
7820 dbug(1,dprintf("V.110,%d",READ_WORD(&bp_parms[3].info[1])));
7821 switch(READ_WORD(&bp_parms[3].info[1])){ /* Rate */
7824 if(READ_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7825 dbug(1,dprintf("56k sync HSCX"));
7830 else if(READ_WORD(bp_parms[0].info)==2){
7831 dbug(1,dprintf("56k async DSP"));
7835 case 50: cai[2] = 1; break;
7836 case 75: cai[2] = 1; break;
7837 case 110: cai[2] = 1; break;
7838 case 150: cai[2] = 1; break;
7839 case 200: cai[2] = 1; break;
7840 case 300: cai[2] = 1; break;
7841 case 600: cai[2] = 1; break;
7842 case 1200: cai[2] = 2; break;
7843 case 2400: cai[2] = 3; break;
7844 case 4800: cai[2] = 4; break;
7845 case 7200: cai[2] = 10; break;
7846 case 9600: cai[2] = 5; break;
7847 case 12000: cai[2] = 13; break;
7848 case 24000: cai[2] = 0; break;
7849 case 14400: cai[2] = 11; break;
7850 case 19200: cai[2] = 6; break;
7851 case 28800: cai[2] = 12; break;
7852 case 38400: cai[2] = 7; break;
7853 case 48000: cai[2] = 8; break;
7854 case 76: cai[2] = 15; break; /* 75/1200 */
7855 case 1201: cai[2] = 14; break; /* 1200/75 */
7856 case 56001: cai[2] = 9; break; /* V.110 56000 */
7859 return _B1_PARM_NOT_SUPPORTED;
7862 if (cai[1] == 13) /* v.110 async */
7864 if (bp_parms[3].length >= 8)
7866 switch (READ_WORD (&bp_parms[3].info[3]))
7869 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7872 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7875 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7878 switch (READ_WORD (&bp_parms[3].info[5]))
7880 case 1: /* odd parity */
7881 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7883 case 2: /* even parity */
7884 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7887 switch (READ_WORD (&bp_parms[3].info[7]))
7889 case 1: /* 2 stop bits */
7890 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7896 else if(cai[1]==8 || READ_WORD(bp_parms[0].info)==3 ){
7897 dbug(1,dprintf("V.110 default 56k sync"));
7903 dbug(1,dprintf("V.110 default 9600 async"));
7907 WRITE_WORD(&cai[5],plci->appl->MaxDataLength);
7908 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]));
7909 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7911 add_p(plci, CAI, cai);
7915 /*------------------------------------------------------------------*/
7916 /* put parameter for b2 and B3 protocol in the parameter buffer */
7917 /*------------------------------------------------------------------*/
7919 word add_b23(PLCI * plci, API_PARSE * bp)
7921 word i, fax_control_bits;
7923 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7924 API_PARSE bp_parms[8];
7925 API_PARSE * b1_config;
7926 API_PARSE * b2_config;
7927 API_PARSE b2_config_parms[8];
7928 API_PARSE * b3_config;
7929 API_PARSE b3_config_parms[6];
7930 API_PARSE global_config[2];
7932 static byte llc[3] = {2,0,0};
7933 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7934 static byte nlc[256];
7935 static byte lli[12] = {1,1};
7937 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7938 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7940 const byte llc3[] = {4,3,2,2,6,6,0};
7941 const byte header[] = {0,2,3,3,0,0,0};
7943 for(i=0;i<8;i++) bp_parms[i].length = 0;
7944 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7945 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7949 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7951 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7954 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7956 if (plci->rx_dma_descriptor <= 0) {
7957 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7958 if (plci->rx_dma_descriptor >= 0)
7959 plci->rx_dma_descriptor++;
7961 if (plci->rx_dma_descriptor > 0) {
7964 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7965 lli[3] = (byte)plci->rx_dma_magic;
7966 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7967 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7968 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7972 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7976 dbug(1,dprintf("add_b23"));
7977 api_save_msg(bp, "s", &plci->B_protocol);
7979 if(!bp->length && plci->tel)
7981 plci->adv_nl = TRUE;
7982 dbug(1,dprintf("Default adv.Nl"));
7983 add_p(plci,LLI,lli);
7984 plci->B2_prot = 1 /*XPARENT*/;
7985 plci->B3_prot = 0 /*XPARENT*/;
7988 add_p(plci, LLC, llc);
7990 WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
7991 add_p(plci, DLC, dlc);
7995 if(!bp->length) /*default*/
7997 dbug(1,dprintf("ret default"));
7998 add_p(plci,LLI,lli);
7999 plci->B2_prot = 0 /*X.75 */;
8000 plci->B3_prot = 0 /*XPARENT*/;
8003 add_p(plci, LLC, llc);
8005 WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
8006 add_p(plci, DLC, dlc);
8009 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8010 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8012 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8014 bp_parms[6].length = 0;
8015 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8017 dbug(1,dprintf("b-form.!"));
8018 return _WRONG_MESSAGE_FORMAT;
8021 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8023 dbug(1,dprintf("b-form.!"));
8024 return _WRONG_MESSAGE_FORMAT;
8027 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8029 if(READ_WORD(bp_parms[1].info)!=1
8030 || READ_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8031 plci->adv_nl = TRUE;
8033 else if(plci->tel) return _B2_NOT_SUPPORTED;
8036 if ((READ_WORD(bp_parms[1].info) == B2_RTP)
8037 && (READ_WORD(bp_parms[2].info) == B3_RTP)
8038 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8040 add_p(plci,LLI,lli);
8041 plci->B2_prot = (byte) READ_WORD(bp_parms[1].info);
8042 plci->B3_prot = (byte) READ_WORD(bp_parms[2].info);
8043 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8045 add_p(plci, LLC, llc);
8047 WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
8048 dlc[3] = 3; /* Addr A */
8049 dlc[4] = 1; /* Addr B */
8050 dlc[5] = 7; /* modulo mode */
8051 dlc[6] = 7; /* window size */
8052 dlc[7] = 0; /* XID len Lo */
8053 dlc[8] = 0; /* XID len Hi */
8054 for (i = 0; i < bp_parms[4].length; i++)
8055 dlc[9+i] = bp_parms[4].info[1+i];
8056 dlc[0] = (byte)(8 + bp_parms[4].length);
8057 add_p(plci, DLC, dlc);
8058 for (i = 0; i < bp_parms[5].length; i++)
8059 nlc[1+i] = bp_parms[5].info[1+i];
8060 nlc[0] = (byte)(bp_parms[5].length);
8061 add_p(plci, NLC, nlc);
8067 if ((READ_WORD(bp_parms[1].info) >= 32)
8068 || (!((1L << READ_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8069 && ((READ_WORD(bp_parms[1].info) != B2_PIAFS)
8070 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8073 return _B2_NOT_SUPPORTED;
8075 if ((READ_WORD(bp_parms[2].info) >= 32)
8076 || !((1L << READ_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8078 return _B3_NOT_SUPPORTED;
8080 if ((READ_WORD(bp_parms[1].info) != B2_SDLC)
8081 && ((READ_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8082 || (READ_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8083 || (READ_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8085 return (add_modem_b23 (plci, bp_parms));
8088 add_p(plci,LLI,lli);
8090 plci->B2_prot = (byte) READ_WORD(bp_parms[1].info);
8091 plci->B3_prot = (byte) READ_WORD(bp_parms[2].info);
8092 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8094 if(bp_parms[6].length)
8096 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8098 return _WRONG_MESSAGE_FORMAT;
8100 switch(READ_WORD(global_config[0].info))
8103 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8106 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8110 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8113 if (plci->B2_prot == B2_PIAFS)
8116 /* IMPLEMENT_PIAFS */
8118 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8119 llc2_out[READ_WORD(bp_parms[1].info)] : llc2_in[READ_WORD(bp_parms[1].info)];
8121 llc[2] = llc3[READ_WORD(bp_parms[2].info)];
8123 add_p(plci, LLC, llc);
8126 WRITE_WORD(&dlc[1], plci->appl->MaxDataLength +
8127 header[READ_WORD(bp_parms[2].info)]);
8129 b1_config = &bp_parms[3];
8131 if(plci->B3_prot == 4
8132 || plci->B3_prot == 5)
8134 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8135 nlc[0] = sizeof(T30_INFO);
8136 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8137 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8138 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8139 if(b1_config->length>=2)
8141 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(READ_WORD(&b1_config->info[1])/2400);
8144 b2_config = &bp_parms[4];
8147 if (llc[1] == PIAFS_CRC)
8149 if (plci->B3_prot != B3_TRANSPARENT)
8151 return _B_STACK_NOT_SUPPORTED;
8153 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8154 return _WRONG_MESSAGE_FORMAT;
8156 WRITE_WORD(&dlc[1],plci->appl->MaxDataLength);
8157 dlc[3] = 0; /* Addr A */
8158 dlc[4] = 0; /* Addr B */
8159 dlc[5] = 0; /* modulo mode */
8160 dlc[6] = 0; /* window size */
8161 if (b2_config->length >= 7){
8164 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8165 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8166 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8167 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8168 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8169 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8170 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8172 if(b2_config->length >= 8) { /* PIAFS control abilities */
8174 dlc[16] = 2; /* Length of PIAFS extention */
8175 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8176 dlc[18] = b2_config_parms[4].info[0]; /* value */
8180 else /* default values, 64K, variable, no compression */
8184 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8185 dlc[10] = 0x03; /* V.42bis P0 */
8186 dlc[11] = 0; /* V.42bis P0 */
8187 dlc[12] = 0; /* V.42bis P1 */
8188 dlc[13] = 0; /* V.42bis P1 */
8189 dlc[14] = 0; /* V.42bis P2 */
8190 dlc[15] = 0; /* V.42bis P2 */
8193 add_p(plci, DLC, dlc);
8197 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8199 if (plci->B3_prot != B3_TRANSPARENT)
8200 return _B_STACK_NOT_SUPPORTED;
8203 WRITE_WORD (&dlc[1], READ_WORD (&dlc[1]) + 2);
8208 if (b2_config->length != 0)
8210 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8211 return _WRONG_MESSAGE_FORMAT;
8213 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8214 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8215 if (b2_config->info[3] != 128)
8217 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8218 return _B2_PARM_NOT_SUPPORTED;
8220 dlc[5] = (byte)(b2_config->info[3] - 1);
8221 dlc[6] = b2_config->info[4];
8222 if(llc[1]==V120_V42BIS){
8223 if (b2_config->length >= 10){
8226 dlc[ 9] = b2_config_parms[4].info[0];
8227 dlc[10] = b2_config_parms[4].info[1];
8228 dlc[11] = b2_config_parms[5].info[0];
8229 dlc[12] = b2_config_parms[5].info[1];
8230 dlc[13] = b2_config_parms[6].info[0];
8231 dlc[14] = b2_config_parms[6].info[1];
8233 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8234 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8235 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8245 if(b2_config->length)
8247 dbug(1,dprintf("B2-Config"));
8248 if(llc[1]==X75_V42BIS){
8249 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8251 return _WRONG_MESSAGE_FORMAT;
8255 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8257 return _WRONG_MESSAGE_FORMAT;
8260 /* if B2 Protocol is LAPD, b2_config structure is different */
8264 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8266 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8268 SAPI = b2_config->info[2]; /* SAPI */
8271 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8273 dlc[3] = 127; /* Mode */
8277 dlc[3] = 7; /* Mode */
8280 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8282 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8283 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8287 dlc[0] = (byte)(b2_config_parms[4].length+6);
8288 dlc[3] = b2_config->info[1];
8289 dlc[4] = b2_config->info[2];
8290 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8291 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8292 return _B2_PARM_NOT_SUPPORTED;
8295 dlc[5] = (byte)(b2_config->info[3]-1);
8296 dlc[6] = b2_config->info[4];
8298 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]));
8299 return _B2_PARM_NOT_SUPPORTED;
8302 if(llc[1]==X75_V42BIS) {
8303 if (b2_config->length >= 10){
8306 dlc[ 9] = b2_config_parms[4].info[0];
8307 dlc[10] = b2_config_parms[4].info[1];
8308 dlc[11] = b2_config_parms[5].info[0];
8309 dlc[12] = b2_config_parms[5].info[1];
8310 dlc[13] = b2_config_parms[6].info[0];
8311 dlc[14] = b2_config_parms[6].info[1];
8313 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8314 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8315 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8323 WRITE_WORD(&dlc[7], (word)b2_config_parms[4].length);
8324 for(i=0; i<b2_config_parms[4].length; i++)
8325 dlc[11+i] = b2_config_parms[4].info[1+i];
8330 add_p(plci, DLC, dlc);
8332 b3_config = &bp_parms[5];
8333 if(b3_config->length)
8335 if(plci->B3_prot == 4
8336 || plci->B3_prot == 5)
8338 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8340 return _WRONG_MESSAGE_FORMAT;
8342 i = READ_WORD((byte *)(b3_config_parms[0].info));
8343 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8344 ((plci->B3_prot == 4) && (((byte)(READ_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8345 ((T30_INFO *)&nlc[1])->data_format = (byte)(READ_WORD((byte *)b3_config_parms[1].info));
8346 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8347 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8348 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8349 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8352 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8353 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8355 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8356 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8357 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8360 ((T30_INFO *)&nlc[1])->recording_properties =
8361 T30_RECORDING_WIDTH_ISO_A3 |
8362 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8363 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8365 if(plci->B3_prot == 5)
8367 if (i & 0x0002) /* Accept incoming fax-polling requests */
8368 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8369 if (i & 0x2000) /* Do not use MR compression */
8370 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8371 if (i & 0x4000) /* Do not use MMR compression */
8372 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8373 if (i & 0x8000) /* Do not use ECM */
8374 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8375 if (plci->fax_connect_info_length != 0)
8377 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8378 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8379 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8380 fax_control_bits |= READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8381 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8384 /* copy station id to NLC */
8387 if(i<b3_config_parms[2].length)
8389 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8393 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8396 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8397 /* copy head line to NLC */
8398 if(b3_config_parms[3].length)
8401 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8404 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8408 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8409 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8410 len = (byte)b3_config_parms[2].length;
8413 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8415 for (i = 0; i < len; i++)
8416 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8417 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8418 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8423 len = (byte)b3_config_parms[3].length;
8424 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8425 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8426 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8427 nlc[0] += (byte)(pos + len);
8428 for (i = 0; i < len; i++)
8429 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8432 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8434 plci->nsf_control_bits = 0;
8435 if(plci->B3_prot == 5)
8437 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8438 && (READ_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8440 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8442 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8443 && (READ_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8445 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8447 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8448 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8450 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8451 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8453 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8454 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8455 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8458 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8459 if (pos < plci->fax_connect_info_length)
8461 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8462 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8466 if (pos < plci->fax_connect_info_length)
8468 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8469 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8473 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8474 & (1L << PRIVATE_FAX_NONSTANDARD))
8476 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8478 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8479 plci->nsf_control_bits = READ_WORD(&plci->fax_connect_info_buffer[pos+2]);
8480 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8481 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8485 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8487 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8492 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8493 plci->nsf_control_bits = READ_WORD(&b3_config_parms[4].info[2]);
8494 nlc[++len] = (byte)(b3_config_parms[4].length);
8495 for (i = 0; i < b3_config_parms[4].length; i++)
8496 nlc[++len] = b3_config_parms[4].info[1+i];
8501 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8502 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8504 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8509 WRITE_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8510 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8511 for (i = 0; i < len; i++)
8512 plci->fax_connect_info_buffer[i] = nlc[1+i];
8513 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8514 i += ((T30_INFO *)&nlc[1])->head_line_len;
8516 plci->fax_connect_info_buffer[len++] = nlc[++i];
8517 plci->fax_connect_info_length = len;
8522 if(b3_config->length!=16)
8523 return _B3_PARM_NOT_SUPPORTED;
8524 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8525 if(READ_WORD(&b3_config->info[13])!=8 && READ_WORD(&b3_config->info[13])!=128)
8526 return _B3_PARM_NOT_SUPPORTED;
8527 nlc[13] = b3_config->info[13];
8528 if(READ_WORD(&b3_config->info[15])>=nlc[13])
8529 return _B3_PARM_NOT_SUPPORTED;
8530 nlc[14] = b3_config->info[15];
8535 if (plci->B3_prot == 4
8536 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8538 add_p(plci, NLC, nlc);
8542 /*----------------------------------------------------------------*/
8543 /* make the same as add_b23, but only for the modem related */
8544 /* L2 and L3 B-Chan protocol. */
8546 /* Enabled L2 and L3 Configurations: */
8547 /* If L1 == Modem all negotiation */
8548 /* only L2 == Modem with full negotiation is allowed */
8549 /* If L1 == Modem async or sync */
8550 /* only L2 == Transparent is allowed */
8551 /* L3 == Modem or L3 == Transparent are allowed */
8552 /* B2 Configuration for modem: */
8553 /* word : enable/disable compression, bitoptions */
8554 /* B3 Configuration for modem: */
8556 /*----------------------------------------------------------------*/
8557 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8559 static byte lli[12] = {1,1};
8560 static byte llc[3] = {2,0,0};
8561 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8562 API_PARSE mdm_config[2];
8566 for(i=0;i<2;i++) mdm_config[i].length = 0;
8567 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8569 if (((READ_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8570 && (READ_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8571 || ((READ_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8572 && (READ_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8574 return (_B_STACK_NOT_SUPPORTED);
8576 if ((READ_WORD(bp_parms[2].info) != B3_MODEM)
8577 && (READ_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8579 return (_B_STACK_NOT_SUPPORTED);
8582 plci->B2_prot = (byte) READ_WORD(bp_parms[1].info);
8583 plci->B3_prot = (byte) READ_WORD(bp_parms[2].info);
8585 if ((READ_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8587 if (api_parse (&bp_parms[4].info[1],
8588 (word)bp_parms[4].length, "w",
8591 return (_WRONG_MESSAGE_FORMAT);
8593 b2_config = READ_WORD(mdm_config[0].info);
8596 /* OK, L2 is modem */
8600 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8602 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8605 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8607 if (plci->rx_dma_descriptor <= 0) {
8608 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8609 if (plci->rx_dma_descriptor >= 0)
8610 plci->rx_dma_descriptor++;
8612 if (plci->rx_dma_descriptor > 0) {
8615 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8616 lli[3] = (byte)plci->rx_dma_magic;
8617 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8618 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8619 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8623 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8627 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8628 /*V42*/ 10 : /*V42_IN*/ 9;
8629 llc[2] = 4; /* pass L3 always transparent */
8630 add_p(plci, LLI, lli);
8631 add_p(plci, LLC, llc);
8633 WRITE_WORD (&dlc[i], plci->appl->MaxDataLength);
8635 if (READ_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8637 if (bp_parms[4].length)
8639 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8640 dlc[i++] = 3; /* Addr A */
8641 dlc[i++] = 1; /* Addr B */
8642 dlc[i++] = 7; /* modulo mode */
8643 dlc[i++] = 7; /* window size */
8644 dlc[i++] = 0; /* XID len Lo */
8645 dlc[i++] = 0; /* XID len Hi */
8647 if (b2_config & MDM_B2_DISABLE_V42bis)
8649 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8651 if (b2_config & MDM_B2_DISABLE_MNP)
8653 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8655 if (b2_config & MDM_B2_DISABLE_TRANS)
8657 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8659 if (b2_config & MDM_B2_DISABLE_V42)
8661 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8663 if (b2_config & MDM_B2_DISABLE_COMP)
8665 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8672 dlc[i++] = 3; /* Addr A */
8673 dlc[i++] = 1; /* Addr B */
8674 dlc[i++] = 7; /* modulo mode */
8675 dlc[i++] = 7; /* window size */
8676 dlc[i++] = 0; /* XID len Lo */
8677 dlc[i++] = 0; /* XID len Hi */
8678 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8679 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8680 DLC_MODEMPROT_DISABLE_V42_DETECT |
8681 DLC_MODEMPROT_DISABLE_COMPRESSION;
8683 dlc[0] = (byte)(i - 1);
8684 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8685 add_p(plci, DLC, dlc);
8690 /*------------------------------------------------------------------*/
8691 /* send a request for the signaling entity */
8692 /*------------------------------------------------------------------*/
8694 void sig_req(PLCI * plci, byte req, byte Id)
8697 if(plci->adapter->adapter_disabled) return;
8698 dbug(1,dprintf("sig_req(%x)",req));
8700 plci->sig_remove_id = plci->Sig.Id;
8701 if(plci->req_in==plci->req_in_start) {
8703 plci->RBuffer[plci->req_in++] = 0;
8705 WRITE_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8706 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8707 plci->RBuffer[plci->req_in++] = req; /* request */
8708 plci->RBuffer[plci->req_in++] = 0; /* channel */
8709 plci->req_in_start = plci->req_in;
8712 /*------------------------------------------------------------------*/
8713 /* send a request for the network layer entity */
8714 /*------------------------------------------------------------------*/
8716 void nl_req_ncci(PLCI * plci, byte req, byte ncci)
8719 if(plci->adapter->adapter_disabled) return;
8720 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8723 plci->nl_remove_id = plci->NL.Id;
8724 ncci_remove (plci, 0, (byte)(ncci != 0));
8727 if(plci->req_in==plci->req_in_start) {
8729 plci->RBuffer[plci->req_in++] = 0;
8731 WRITE_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8732 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8733 plci->RBuffer[plci->req_in++] = req; /* request */
8734 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8735 plci->req_in_start = plci->req_in;
8738 void send_req(PLCI * plci)
8745 if(plci->adapter->adapter_disabled) return;
8746 channel_xmit_xon (plci);
8748 /* if nothing to do, return */
8749 if(plci->req_in==plci->req_out) return;
8750 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8752 if(plci->nl_req || plci->sig_req) return;
8754 l = READ_WORD(&plci->RBuffer[plci->req_out]);
8756 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8758 if(plci->RBuffer[plci->req_out]==1)
8762 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8763 e->ReqCh = plci->RBuffer[plci->req_out++];
8767 plci->RBuffer[plci->req_out-4] = CAI;
8768 plci->RBuffer[plci->req_out-3] = 1;
8769 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8770 plci->RBuffer[plci->req_out-1] = 0;
8772 plci->nl_global_req = plci->nl_req;
8774 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8779 if(plci->RBuffer[plci->req_out])
8780 e->Id = plci->RBuffer[plci->req_out];
8782 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8783 e->ReqCh = plci->RBuffer[plci->req_out++];
8785 plci->sig_global_req = plci->sig_req;
8786 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8788 plci->XData[0].PLength = l;
8790 plci->adapter->request(e);
8791 dbug(1,dprintf("send_ok"));
8794 void send_data(PLCI * plci)
8796 DIVA_CAPI_ADAPTER * a;
8797 DATA_B3_DESC * data;
8801 if (!plci->nl_req && plci->ncci_ring_list)
8804 ncci = plci->ncci_ring_list;
8807 ncci = a->ncci_next[ncci];
8808 ncci_ptr = &(a->ncci[ncci]);
8809 if (!(a->ncci_ch[ncci]
8810 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8812 if (ncci_ptr->data_pending)
8814 if ((a->ncci_state[ncci] == CONNECTED)
8815 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8816 || (plci->send_disc == ncci))
8818 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8819 if ((plci->B2_prot == B2_V120_ASYNC)
8820 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8821 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8823 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8824 plci->NData[1].PLength = data->Length;
8825 if (data->Flags & 0x10)
8826 plci->NData[0].P = v120_break_header;
8828 plci->NData[0].P = v120_default_header;
8829 plci->NData[0].PLength = 1 ;
8831 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8835 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8836 plci->NData[0].PLength = data->Length;
8837 if (data->Flags & 0x10)
8838 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8840 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8841 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8844 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8846 plci->NL.X = plci->NData;
8847 plci->NL.ReqCh = a->ncci_ch[ncci];
8848 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8849 plci->data_sent = TRUE;
8850 plci->data_sent_ptr = data->P;
8851 a->request(&plci->NL);
8854 cleanup_ncci_data (plci, ncci);
8857 else if (plci->send_disc == ncci)
8859 /* dprintf("N_DISC"); */
8860 plci->NData[0].PLength = 0;
8861 plci->NL.ReqCh = a->ncci_ch[ncci];
8862 plci->NL.Req = plci->nl_req = N_DISC;
8863 a->request(&plci->NL);
8864 plci->command = _DISCONNECT_B3_R;
8865 plci->send_disc = 0;
8868 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8869 plci->ncci_ring_list = ncci;
8873 void listen_check(DIVA_CAPI_ADAPTER * a)
8877 byte activnotifiedcalls = 0;
8879 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8880 if (!remove_started && !a->adapter_disabled)
8882 for(i=0;i<a->max_plci;i++)
8884 plci = &(a->plci[i]);
8885 if(plci->notifiedcall) activnotifiedcalls++;
8887 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8889 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8890 if((j=get_plci(a))) {
8892 plci = &a->plci[j-1];
8893 plci->State = LISTENING;
8895 add_p(plci,OAD,"\x01\xfd");
8897 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8899 add_p(plci,CAI,"\x01\xc0");
8900 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8901 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8902 add_p(plci,SHIFT|6,NULL);
8903 add_p(plci,SIN,"\x02\x00\x00");
8904 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8905 sig_req(plci,ASSIGN,DSIG_ID);
8912 /*------------------------------------------------------------------*/
8913 /* functions for all parameters sent in INDs */
8914 /*------------------------------------------------------------------*/
8916 void IndParse(PLCI * plci, word * parms_id, byte ** parms, byte multiIEsize)
8918 word ploc; /* points to current location within packet */
8930 in = plci->Sig.RBuffer->P;
8931 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8932 { /* element but parms array is larger */
8933 parms[i] = (byte *)"";
8935 for(i=0; i<multiIEsize; i++)
8937 parms[i] = (byte *)"";
8940 while(ploc<plci->Sig.RBuffer->length-1) {
8942 /* read information element id and length */
8946 /* w &=0xf0; removed, cannot detect congestion levels */
8947 /* upper 4 bit masked with w==SHIFT now */
8951 wlen = (byte)(in[ploc+1]+1);
8953 /* check if length valid (not exceeding end of packet) */
8954 if((ploc+wlen) > 270) return ;
8955 if(lock & 0x80) lock &=0x7f;
8956 else codeset = lock;
8958 if((w&0xf0)==SHIFT) {
8960 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8965 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8967 code |= (codeset<<8);
8969 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8971 if(i<parms_id[0]+1) {
8972 if(!multiIEsize) { /* with multiIEs use next field index, */
8973 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8976 parms[mIEindex] = &in[ploc+1];
8977 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8979 || parms_id[i]==CONN_NR
8980 || parms_id[i]==CAD) {
8981 if(in[ploc+2] &0x80) {
8982 in[ploc+0] = (byte)(in[ploc+1]+1);
8983 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8985 parms[mIEindex] = &in[ploc];
8988 mIEindex++; /* effects multiIEs only */
8997 /*------------------------------------------------------------------*/
8998 /* try to match a cip from received BC and HLC */
8999 /*------------------------------------------------------------------*/
9001 byte ie_compare(byte * ie1, byte * ie2)
9004 if(!ie1 || ! ie2) return FALSE;
9005 if(!ie1[0]) return FALSE;
9006 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return FALSE;
9010 word find_cip(DIVA_CAPI_ADAPTER * a, byte * bc, byte * hlc)
9015 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9018 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9024 static byte AddInfo(byte **add_i,
9034 /* facility is a nested structure */
9035 /* FTY can be more than once */
9037 if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9039 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9044 add_i[0] = (byte *)"";
9048 add_i[3] = (byte *)"";
9051 { /* facility array found */
9052 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9054 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9058 facility[j++]=0x1c; /* copy fac IE */
9059 for(k=0;k<=flen;k++,j++)
9061 facility[j]=fty_i[i][k];
9062 /* dbug(1,dprintf("%x ",facility[j])); */
9066 add_i[3] = facility;
9068 /* dbug(1,dprintf("FacArrLen=%d ",len)); */
9069 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9070 len += 4; /* calculate length of all */
9074 /*------------------------------------------------------------------*/
9075 /* voice and codec features */
9076 /*------------------------------------------------------------------*/
9078 void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER * a)
9080 byte voice_chi[] = "\x02\x18\x01";
9083 channel = chi[chi[0]]&0x3;
9084 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9085 voice_chi[2] = (channel) ? channel : 1;
9086 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9087 add_p(plci,ESC,voice_chi); /* Channel */
9088 sig_req(plci,TEL_CTRL,0);
9090 if(a->AdvSignalPLCI)
9092 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9096 void VoiceChannelOff(PLCI *plci)
9098 dbug(1,dprintf("ExtDevOFF"));
9099 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9100 sig_req(plci,TEL_CTRL,0);
9102 if(plci->adapter->AdvSignalPLCI)
9104 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9109 word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, byte hook_listen)
9114 /* check if hardware supports handset with hook states (adv.codec) */
9115 /* or if just a on board codec is supported */
9116 /* the advanced codec plci is just for internal use */
9118 /* diva Pro with on-board codec: */
9119 if(a->profile.Global_Options & HANDSET)
9121 /* new call, but hook states are already signalled */
9124 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9126 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9127 return 0x2001; /* codec in use by another application */
9131 a->AdvSignalPLCI = plci;
9132 plci->tel=ADV_VOICE;
9134 return 0; /* adv codec still used */
9138 splci = &a->plci[j-1];
9139 splci->tel = CODEC_PERMANENT;
9140 /* hook_listen indicates if a facility_req with handset/hook support */
9141 /* was sent. Otherwise if just a call on an external device was made */
9142 /* the codec will be used but the hook info will be discarded (just */
9143 /* the external controller is in use */
9144 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9147 splci->State = ADVANCED_VOICE_NOSIG;
9150 plci->spoofed_msg = SPOOFING_REQUIRED;
9152 /* indicate D-ch connect if */
9153 } /* codec is connected OK */
9156 a->AdvSignalPLCI = plci;
9157 plci->tel=ADV_VOICE;
9159 a->AdvSignalAppl = appl;
9160 a->AdvCodecFLAG = TRUE;
9161 a->AdvCodecPLCI = splci;
9162 add_p(splci,CAI,"\x01\x15");
9163 add_p(splci,LLI,"\x01\x00");
9164 add_p(splci,ESC,"\x02\x18\x00");
9165 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9166 splci->internal_command = PERM_COD_ASSIGN;
9167 dbug(1,dprintf("Codec Assign"));
9168 sig_req(splci,ASSIGN,DSIG_ID);
9173 return 0x2001; /* wrong state, no more plcis */
9176 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9178 if(hook_listen) return 0x300B; /* Facility not supported */
9179 /* no hook with SCOM */
9180 if(plci!=0) plci->tel = CODEC;
9181 dbug(1,dprintf("S/SCOM codec"));
9182 /* first time we use the scom-s codec we must shut down the internal */
9183 /* handset application of the card. This can be done by an assign with */
9184 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9185 if(!a->scom_appl_disable){
9186 if((j=get_plci(a))) {
9187 splci = &a->plci[j-1];
9188 add_p(splci,CAI,"\x01\x80");
9189 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9190 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9192 a->scom_appl_disable = TRUE;
9195 return 0x2001; /* wrong state, no more plcis */
9199 else return 0x300B; /* Facility not supported */
9205 void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9208 dbug(1,dprintf("CodecIdCheck"));
9210 if(a->AdvSignalPLCI == plci)
9212 dbug(1,dprintf("PLCI owns codec"));
9213 VoiceChannelOff(a->AdvCodecPLCI);
9214 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9216 dbug(1,dprintf("remove temp codec PLCI"));
9217 plci_remove(a->AdvCodecPLCI);
9218 a->AdvCodecFLAG = 0;
9219 a->AdvCodecPLCI = NULL;
9220 a->AdvSignalAppl = NULL;
9222 a->AdvSignalPLCI = NULL;
9226 /* -------------------------------------------------------------------
9227 Ask for physical address of card on PCI bus
9228 ------------------------------------------------------------------- */
9229 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9230 IDI_SYNC_REQ * preq) {
9232 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9233 ENTITY * e = (ENTITY *)preq;
9235 e->user[0] = a->Id - 1;
9236 preq->xdi_sdram_bar.info.bar = 0;
9237 preq->xdi_sdram_bar.Req = 0;
9238 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9242 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9243 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9247 /* -------------------------------------------------------------------
9248 Ask XDI about extended features
9249 ------------------------------------------------------------------- */
9250 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9251 IDI_SYNC_REQ * preq;
9252 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9255 preq = (IDI_SYNC_REQ *)&buffer[0];
9257 if (!diva_xdi_extended_features) {
9258 ENTITY * e = (ENTITY *)preq;
9259 diva_xdi_extended_features |= 0x80000000;
9261 e->user[0] = a->Id - 1;
9262 preq->xdi_extended_features.Req = 0;
9263 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9264 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9265 preq->xdi_extended_features.info.features = &features[0];
9269 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9271 Check features located in the byte '0'
9273 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9274 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9276 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9277 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9278 dbug(1,dprintf("XDI provides RxDMA"));
9280 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9281 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9283 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9284 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9285 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9291 diva_ask_for_xdi_sdram_bar (a, preq);
9294 /*------------------------------------------------------------------*/
9296 /*------------------------------------------------------------------*/
9297 /* called from OS specific part after init time to get the Law */
9298 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9299 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9304 if(a->automatic_law) {
9307 if((j=get_plci(a))) {
9308 diva_get_extended_adapter_features (a);
9309 splci = &a->plci[j-1];
9310 a->automatic_lawPLCI = splci;
9311 a->automatic_law = 1;
9312 add_p(splci,CAI,"\x01\x80");
9313 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9314 splci->internal_command = USELAW_REQ;
9317 sig_req(splci,ASSIGN,DSIG_ID);
9322 /* called from OS specific part if an application sends an Capi20Release */
9323 word CapiRelease(word Id)
9325 word i, j, appls_found;
9328 DIVA_CAPI_ADAPTER *a;
9332 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9333 return (_WRONG_APPL_ID);
9336 this = &application[Id-1]; /* get application pointer */
9338 for(i=0,appls_found=0; i<max_appl; i++)
9340 if(application[i].Id) /* an application has been found */
9346 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9351 a->Info_Mask[Id-1] = 0;
9352 a->CIP_Mask[Id-1] = 0;
9353 a->Notification_Mask[Id-1] = 0;
9354 a->codec_listen[Id-1] = NULL;
9355 a->requested_options_table[Id-1] = 0;
9356 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9357 { /* with this application */
9359 if(plci->Id) /* if plci owns no application */
9360 { /* it may be not jet connected */
9361 if(plci->State==INC_CON_PENDING
9362 || plci->State==INC_CON_ALERT)
9364 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9366 clear_c_ind_mask_bit (plci, (word)(Id-1));
9367 if(c_ind_mask_empty (plci))
9369 sig_req(plci,HANGUP,0);
9371 plci->State = OUTG_DIS_PENDING;
9375 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9377 clear_c_ind_mask_bit (plci, (word)(Id-1));
9378 if(c_ind_mask_empty (plci))
9387 if(plci->appl==this)
9397 if(a->flag_dynamic_l1_down)
9399 if(appls_found==1) /* last application does a capi release */
9403 plci = &a->plci[j-1];
9405 add_p(plci,OAD,"\x01\xfd");
9406 add_p(plci,CAI,"\x01\x80");
9407 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9408 add_p(plci,SHIFT|6,NULL);
9409 add_p(plci,SIN,"\x02\x00\x00");
9410 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9411 sig_req(plci,ASSIGN,DSIG_ID);
9412 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9413 sig_req(plci,SIG_CTRL,0);
9418 if(a->AdvSignalAppl==this)
9420 this->NullCREnable = FALSE;
9421 if (a->AdvCodecPLCI)
9423 plci_remove(a->AdvCodecPLCI);
9424 a->AdvCodecPLCI->tel = 0;
9425 a->AdvCodecPLCI->adv_nl = 0;
9427 a->AdvSignalAppl = NULL;
9428 a->AdvSignalPLCI = NULL;
9429 a->AdvCodecFLAG = 0;
9430 a->AdvCodecPLCI = NULL;
9440 static word plci_remove_check(PLCI *plci)
9442 if(!plci) return TRUE;
9443 if(!plci->NL.Id && c_ind_mask_empty (plci))
9445 if(plci->Sig.Id == 0xff)
9449 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9450 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9453 CodecIdCheck(plci->adapter, plci);
9454 clear_b1_config (plci);
9455 ncci_remove (plci, 0, FALSE);
9456 plci_free_msg_in_queue (plci);
9457 channel_flow_control_remove (plci);
9462 plci->notifiedcall = 0;
9464 listen_check(plci->adapter);
9472 /*------------------------------------------------------------------*/
9474 static byte plci_nl_busy (PLCI *plci)
9476 /* only applicable for non-multiplexed protocols */
9477 return (plci->nl_req
9478 || (plci->ncci_ring_list
9479 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9480 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9484 /*------------------------------------------------------------------*/
9485 /* DTMF facilities */
9486 /*------------------------------------------------------------------*/
9495 } dtmf_digit_map[] =
9497 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9498 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9499 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9500 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9501 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9502 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9503 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9504 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9505 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9506 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9507 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9508 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9509 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9510 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9511 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9512 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9513 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9514 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9515 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9516 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9518 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9519 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9520 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9521 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9522 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9523 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9524 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9525 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9526 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9527 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9528 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9529 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9530 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9531 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9532 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9533 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9534 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9535 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9536 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9537 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9538 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9539 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9540 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9541 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9542 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9543 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9544 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9545 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9546 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9547 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9548 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9549 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9550 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9551 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9552 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9553 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9554 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9555 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9556 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9557 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9558 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9559 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9560 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9561 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9562 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9563 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9564 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9565 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9566 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9567 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9568 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9569 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9573 #define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0]))
9576 static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9578 word min_digit_duration, min_gap_duration;
9580 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9581 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9582 (char *)(FILE_), __LINE__, enable_mask));
9584 if (enable_mask != 0)
9586 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9587 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9588 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9589 WRITE_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9590 WRITE_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9591 plci->NData[0].PLength = 5;
9593 WRITE_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9594 plci->NData[0].PLength += 2;
9595 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9600 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9601 plci->NData[0].PLength = 1;
9603 capidtmf_recv_disable (&(plci->capidtmf_state));
9606 plci->NData[0].P = plci->internal_req_buffer;
9607 plci->NL.X = plci->NData;
9609 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9610 plci->adapter->request (&plci->NL);
9614 static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9618 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9619 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9620 (char *)(FILE_), __LINE__, digit_count));
9622 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9623 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9624 WRITE_WORD (&plci->internal_req_buffer[1], w);
9625 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9626 WRITE_WORD (&plci->internal_req_buffer[3], w);
9627 for (i = 0; i < digit_count; i++)
9630 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9631 && (digit_buffer[i] != dtmf_digit_map[w].character))
9635 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9636 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9638 plci->NData[0].PLength = 5 + digit_count;
9639 plci->NData[0].P = plci->internal_req_buffer;
9640 plci->NL.X = plci->NData;
9642 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9643 plci->adapter->request (&plci->NL);
9647 static void dtmf_rec_clear_config (PLCI *plci)
9650 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9651 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9652 (char *)(FILE_), __LINE__));
9654 plci->dtmf_rec_active = 0;
9655 plci->dtmf_rec_pulse_ms = 0;
9656 plci->dtmf_rec_pause_ms = 0;
9658 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9663 static void dtmf_send_clear_config (PLCI *plci)
9666 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9667 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9668 (char *)(FILE_), __LINE__));
9670 plci->dtmf_send_requests = 0;
9671 plci->dtmf_send_pulse_ms = 0;
9672 plci->dtmf_send_pause_ms = 0;
9676 static void dtmf_prepare_switch (dword Id, PLCI *plci)
9679 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9680 UnMapId (Id), (char *)(FILE_), __LINE__));
9682 while (plci->dtmf_send_requests != 0)
9683 dtmf_confirmation (Id, plci);
9687 static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9690 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9691 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9697 static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9701 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9702 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9705 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9707 switch (plci->adjust_b_state)
9709 case ADJUST_B_RESTORE_DTMF_1:
9710 plci->internal_command = plci->adjust_b_command;
9711 if (plci_nl_busy (plci))
9713 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9716 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9717 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9719 case ADJUST_B_RESTORE_DTMF_2:
9720 if ((Rc != OK) && (Rc != OK_FC))
9722 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9723 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9724 Info = _WRONG_STATE;
9734 static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9736 word internal_command, Info;
9740 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9741 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9742 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9743 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9747 WRITE_WORD (&result[1], DTMF_SUCCESS);
9748 internal_command = plci->internal_command;
9749 plci->internal_command = 0;
9751 switch (plci->dtmf_cmd)
9754 case DTMF_LISTEN_TONE_START:
9756 case DTMF_LISTEN_MF_START:
9759 case DTMF_LISTEN_START:
9760 switch (internal_command)
9763 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9764 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9765 case DTMF_COMMAND_1:
9766 if (adjust_b_process (Id, plci, Rc) != GOOD)
9768 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9769 UnMapId (Id), (char *)(FILE_), __LINE__));
9770 Info = _FACILITY_NOT_SUPPORTED;
9773 if (plci->internal_command)
9775 case DTMF_COMMAND_2:
9776 if (plci_nl_busy (plci))
9778 plci->internal_command = DTMF_COMMAND_2;
9781 plci->internal_command = DTMF_COMMAND_3;
9782 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9784 case DTMF_COMMAND_3:
9785 if ((Rc != OK) && (Rc != OK_FC))
9787 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9788 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9789 Info = _FACILITY_NOT_SUPPORTED;
9793 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9795 plci->dtmf_rec_active |= mask;
9801 case DTMF_LISTEN_TONE_STOP:
9803 case DTMF_LISTEN_MF_STOP:
9806 case DTMF_LISTEN_STOP:
9807 switch (internal_command)
9810 plci->dtmf_rec_active &= ~mask;
9811 if (plci->dtmf_rec_active)
9814 case DTMF_COMMAND_1:
9815 if (plci->dtmf_rec_active)
9817 if (plci_nl_busy (plci))
9819 plci->internal_command = DTMF_COMMAND_1;
9822 plci->dtmf_rec_active &= ~mask;
9823 plci->internal_command = DTMF_COMMAND_2;
9824 dtmf_enable_receiver (plci, FALSE);
9828 case DTMF_COMMAND_2:
9829 if ((Rc != OK) && (Rc != OK_FC))
9831 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9832 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9833 Info = _FACILITY_NOT_SUPPORTED;
9837 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9838 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9839 case DTMF_COMMAND_3:
9840 if (adjust_b_process (Id, plci, Rc) != GOOD)
9842 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9843 UnMapId (Id), (char *)(FILE_), __LINE__));
9844 Info = _FACILITY_NOT_SUPPORTED;
9847 if (plci->internal_command)
9854 case DTMF_SEND_TONE:
9859 case DTMF_DIGITS_SEND:
9860 switch (internal_command)
9863 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9864 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9866 case DTMF_COMMAND_1:
9867 if (adjust_b_process (Id, plci, Rc) != GOOD)
9869 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9870 UnMapId (Id), (char *)(FILE_), __LINE__));
9871 Info = _FACILITY_NOT_SUPPORTED;
9874 if (plci->internal_command)
9876 case DTMF_COMMAND_2:
9877 if (plci_nl_busy (plci))
9879 plci->internal_command = DTMF_COMMAND_2;
9882 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9883 plci->internal_command = DTMF_COMMAND_3;
9884 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9886 case DTMF_COMMAND_3:
9887 if ((Rc != OK) && (Rc != OK_FC))
9889 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9890 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9891 if (plci->dtmf_send_requests != 0)
9892 (plci->dtmf_send_requests)--;
9893 Info = _FACILITY_NOT_SUPPORTED;
9900 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9901 "wws", Info, SELECTOR_DTMF, result);
9905 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9910 API_PARSE dtmf_parms[5];
9913 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9914 UnMapId (Id), (char *)(FILE_), __LINE__));
9918 WRITE_WORD (&result[1], DTMF_SUCCESS);
9919 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9921 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9922 UnMapId (Id), (char *)(FILE_), __LINE__));
9923 Info = _FACILITY_NOT_SUPPORTED;
9925 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9927 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9928 UnMapId (Id), (char *)(FILE_), __LINE__));
9929 Info = _WRONG_MESSAGE_FORMAT;
9932 else if ((READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9933 || (READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9935 if (!((a->requested_options_table[appl->Id-1])
9936 & (1L << PRIVATE_DTMF_TONE)))
9938 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9939 UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info)));
9940 WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9944 for (i = 0; i < 32; i++)
9946 if (READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9948 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9950 if (dtmf_digit_map[i].listen_mask != 0)
9951 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9956 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9958 if (dtmf_digit_map[i].send_mask != 0)
9959 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9967 else if (plci == NULL)
9969 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9970 UnMapId (Id), (char *)(FILE_), __LINE__));
9971 Info = _WRONG_IDENTIFIER;
9976 || !plci->NL.Id || plci->nl_remove_id)
9978 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9979 UnMapId (Id), (char *)(FILE_), __LINE__));
9980 Info = _WRONG_STATE;
9985 plci->dtmf_cmd = READ_WORD (dtmf_parms[0].info);
9987 switch (plci->dtmf_cmd)
9990 case DTMF_LISTEN_TONE_START:
9991 case DTMF_LISTEN_TONE_STOP:
9993 case DTMF_LISTEN_MF_START:
9994 case DTMF_LISTEN_MF_STOP:
9996 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9997 & (1L << PRIVATE_DTMF_TONE)))
9999 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10000 UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info)));
10001 WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10005 case DTMF_LISTEN_START:
10006 case DTMF_LISTEN_STOP:
10007 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10008 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10010 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10011 UnMapId (Id), (char *)(FILE_), __LINE__));
10012 Info = _FACILITY_NOT_SUPPORTED;
10015 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10017 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10019 plci->dtmf_rec_pulse_ms = 0;
10020 plci->dtmf_rec_pause_ms = 0;
10024 plci->dtmf_rec_pulse_ms = READ_WORD (dtmf_parms[1].info);
10025 plci->dtmf_rec_pause_ms = READ_WORD (dtmf_parms[2].info);
10028 start_internal_command (Id, plci, dtmf_command);
10032 case DTMF_SEND_TONE:
10036 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10037 & (1L << PRIVATE_DTMF_TONE)))
10039 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10040 UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info)));
10041 WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10045 case DTMF_DIGITS_SEND:
10046 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10048 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10049 UnMapId (Id), (char *)(FILE_), __LINE__));
10050 Info = _WRONG_MESSAGE_FORMAT;
10053 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10055 plci->dtmf_send_pulse_ms = READ_WORD (dtmf_parms[1].info);
10056 plci->dtmf_send_pause_ms = READ_WORD (dtmf_parms[2].info);
10060 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10063 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10064 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10065 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10071 if (j == DTMF_DIGIT_MAP_ENTRIES)
10073 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10074 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10075 WRITE_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10078 if (plci->dtmf_send_requests >=
10079 sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0]))
10081 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10082 UnMapId (Id), (char *)(FILE_), __LINE__));
10083 Info = _WRONG_STATE;
10086 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10087 start_internal_command (Id, plci, dtmf_command);
10091 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10092 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10093 WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10097 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10098 "wws", Info, SELECTOR_DTMF, result);
10103 static void dtmf_confirmation (dword Id, PLCI *plci)
10109 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10110 UnMapId (Id), (char *)(FILE_), __LINE__));
10114 WRITE_WORD (&result[1], DTMF_SUCCESS);
10115 if (plci->dtmf_send_requests != 0)
10117 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10118 "wws", GOOD, SELECTOR_DTMF, result);
10119 (plci->dtmf_send_requests)--;
10120 for (i = 0; i < plci->dtmf_send_requests; i++)
10121 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10126 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10130 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10131 UnMapId (Id), (char *)(FILE_), __LINE__));
10134 for (i = 1; i < length; i++)
10137 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10138 && ((msg[i] != dtmf_digit_map[j].code)
10139 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10143 if (j < DTMF_DIGIT_MAP_ENTRIES)
10146 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10147 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10148 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10152 for (i = length; i > n + 1; i--)
10153 msg[i] = msg[i - 1];
10157 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10159 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10161 msg[++n] = dtmf_digit_map[j].character;
10167 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10172 /*------------------------------------------------------------------*/
10173 /* DTMF parameters */
10174 /*------------------------------------------------------------------*/
10176 static void dtmf_parameter_write (PLCI *plci)
10179 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10181 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10182 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10183 (char *)(FILE_), __LINE__));
10185 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10186 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10187 for (i = 0; i < plci->dtmf_parameter_length; i++)
10188 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10189 add_p (plci, FTY, parameter_buffer);
10190 sig_req (plci, TEL_CTRL, 0);
10195 static void dtmf_parameter_clear_config (PLCI *plci)
10198 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10199 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10200 (char *)(FILE_), __LINE__));
10202 plci->dtmf_parameter_length = 0;
10206 static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10209 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10210 UnMapId (Id), (char *)(FILE_), __LINE__));
10215 static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10218 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10219 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10225 static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10229 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10230 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10233 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10234 && (plci->dtmf_parameter_length != 0))
10236 switch (plci->adjust_b_state)
10238 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10239 plci->internal_command = plci->adjust_b_command;
10242 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10245 dtmf_parameter_write (plci);
10246 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10248 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10249 if ((Rc != OK) && (Rc != OK_FC))
10251 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10252 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10253 Info = _WRONG_STATE;
10263 /*------------------------------------------------------------------*/
10264 /* Line interconnect facilities */
10265 /*------------------------------------------------------------------*/
10268 LI_CONFIG *li_config_table;
10269 word li_total_channels;
10272 /*------------------------------------------------------------------*/
10273 /* translate a CHI information element to a channel number */
10274 /* returns 0xff - any channel */
10275 /* 0xfe - chi wrong coding */
10276 /* 0xfd - D-channel */
10277 /* 0x00 - no channel */
10278 /* else channel number / PRI: timeslot */
10279 /* if channels is provided we accept more than one channel. */
10280 /*------------------------------------------------------------------*/
10282 static byte chi_to_channel (byte *chi, dword *pchannelmap)
10291 if (pchannelmap) *pchannelmap = 0;
10292 if(!chi[0]) return 0xff;
10295 if(chi[1] & 0x20) {
10296 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10297 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10298 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10299 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10300 if(chi[1] &0x08) excl = 0x40;
10302 /* int. id present */
10305 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10306 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10309 /* coding standard, Number/Map, Channel Type */
10311 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10312 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10313 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10319 if((chi[0]-p)==4) ofs = 0;
10320 else if((chi[0]-p)==3) ofs = 1;
10324 for(i=0; i<4 && p<chi[0]; i++) {
10329 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10342 if((byte)(chi[0]-p)>30) return 0xfe;
10344 for(i=p; i<=chi[0]; i++) {
10345 if ((chi[i] &0x7f) > 31) return 0xfe;
10346 map |= (1L << (chi[i] &0x7f));
10350 if(p!=chi[0]) return 0xfe;
10351 if (ch > 31) return 0xfe;
10354 if(chi[p] &0x40) return 0xfe;
10356 if (pchannelmap) *pchannelmap = map;
10357 else if (map != ((dword)(1L << ch))) return 0xfe;
10358 return (byte)(excl | ch);
10360 else { /* not PRI */
10361 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10362 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10363 if(chi[1] &0x08) excl = 0x40;
10365 switch(chi[1] |0x98) {
10366 case 0x98: return 0;
10368 if (pchannelmap) *pchannelmap = 2;
10371 if (pchannelmap) *pchannelmap = 4;
10373 case 0x9b: return 0xff;
10374 case 0x9c: return 0xfd; /* d-ch */
10375 default: return 0xfe;
10381 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10383 DIVA_CAPI_ADAPTER *a;
10388 old_id = plci->li_bchannel_id;
10391 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10392 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10393 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10394 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10395 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10399 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10401 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10402 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10403 plci->li_bchannel_id = bchannel_id & 0x03;
10404 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10406 splci = a->AdvSignalPLCI;
10407 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10409 if ((splci->li_bchannel_id != 0)
10410 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10412 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10414 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10415 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10416 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10417 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10418 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10421 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10422 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10425 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10426 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10428 mixer_clear_config (plci);
10430 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10431 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10432 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10436 static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10438 DIVA_CAPI_ADAPTER *a;
10443 old_id = plci->li_bchannel_id;
10444 ch = chi_to_channel (chi, NULL);
10449 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10450 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10451 plci->li_bchannel_id = (ch & 0x1f) + 1;
10452 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10453 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10457 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10459 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10460 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10461 plci->li_bchannel_id = ch & 0x1f;
10462 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10464 splci = a->AdvSignalPLCI;
10465 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10467 if ((splci->li_bchannel_id != 0)
10468 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10470 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10472 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10473 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10474 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10475 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10476 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10479 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10480 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10484 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10485 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10487 mixer_clear_config (plci);
10489 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10490 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10491 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10495 #define MIXER_MAX_DUMP_CHANNELS 34
10497 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10499 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10502 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10504 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10505 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10507 for (i = 0; i < li_total_channels; i++)
10509 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10510 if (li_config_table[i].chflags != 0)
10511 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10514 for (j = 0; j < li_total_channels; j++)
10516 if (((li_config_table[i].flag_table[j]) != 0)
10517 || ((li_config_table[j].flag_table[i]) != 0))
10519 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10521 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10522 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10524 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10529 for (i = 0; i < li_total_channels; i++)
10531 for (j = 0; j < li_total_channels; j++)
10533 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10534 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10535 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10538 for (n = 0; n < li_total_channels; n++)
10540 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10542 for (i = 0; i < li_total_channels; i++)
10544 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10546 for (j = 0; j < li_total_channels; j++)
10548 li_config_table[i].coef_table[j] |=
10549 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10555 for (i = 0; i < li_total_channels; i++)
10557 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10559 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10560 for (j = 0; j < li_total_channels; j++)
10562 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10563 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10565 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10566 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10569 for (i = 0; i < li_total_channels; i++)
10571 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10573 for (j = 0; j < li_total_channels; j++)
10575 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10576 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10577 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10578 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10579 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10580 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10581 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10582 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10584 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10586 for (j = 0; j < li_total_channels; j++)
10588 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10590 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10591 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10592 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10596 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10598 for (j = 0; j < li_total_channels; j++)
10600 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10601 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10604 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10606 for (j = 0; j < li_total_channels; j++)
10608 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10610 for (n = 0; n < li_total_channels; n++)
10612 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10614 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10615 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10617 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10618 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10619 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10621 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10622 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10630 for (i = 0; i < li_total_channels; i++)
10632 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10634 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10635 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10636 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10637 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10638 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10639 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10640 for (j = 0; j < li_total_channels; j++)
10642 if ((li_config_table[i].flag_table[j] &
10643 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10644 || (li_config_table[j].flag_table[i] &
10645 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10647 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10649 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10650 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10651 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10652 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10654 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10656 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10657 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10661 for (i = 0; i < li_total_channels; i++)
10663 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10666 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10668 if (j < li_total_channels)
10670 for (j = 0; j < li_total_channels; j++)
10672 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10673 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10674 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10679 n = li_total_channels;
10680 if (n > MIXER_MAX_DUMP_CHANNELS)
10681 n = MIXER_MAX_DUMP_CHANNELS;
10683 for (j = 0; j < n; j++)
10685 if ((j & 0x7) == 0)
10687 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10688 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10691 dbug (1, dprintf ("[%06lx] CURRENT %s",
10692 (dword)(UnMapController (a->Id)), (char *) hex_line));
10694 for (j = 0; j < n; j++)
10696 if ((j & 0x7) == 0)
10698 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10699 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10702 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10703 (dword)(UnMapController (a->Id)), (char *) hex_line));
10705 for (j = 0; j < n; j++)
10707 if ((j & 0x7) == 0)
10709 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10710 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10713 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10714 (dword)(UnMapController (a->Id)), (char *) hex_line));
10715 for (i = 0; i < n; i++)
10718 for (j = 0; j < n; j++)
10720 if ((j & 0x7) == 0)
10722 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10723 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10726 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10727 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10729 for (i = 0; i < n; i++)
10732 for (j = 0; j < n; j++)
10734 if ((j & 0x7) == 0)
10736 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10737 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10740 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10741 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10750 } mixer_write_prog_pri[] =
10752 { LI_COEF_CH_CH, 0 },
10753 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10754 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10755 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10763 byte xconnect_override;
10764 } mixer_write_prog_bri[] =
10766 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10767 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10768 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10769 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10770 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10771 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10772 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10773 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10774 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10775 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10776 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10777 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10778 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10779 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10780 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10781 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10782 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10783 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10784 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10785 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10786 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10787 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10788 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10789 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10790 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10791 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10792 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10793 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10794 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10795 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10796 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10797 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10798 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10799 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10800 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10801 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10804 static byte mixer_swapped_index_bri[] =
10807 19, /* Alt B to B */
10809 21, /* Alt PC to B */
10811 23, /* Alt IC to B */
10813 25, /* Alt B to PC */
10815 27, /* Alt PC to PC */
10817 29, /* Alt IC to PC */
10819 31, /* Alt B to IC */
10821 33, /* Alt PC to IC */
10823 35, /* Alt IC to IC */
10824 0, /* Alt B to Alt B */
10825 1, /* B to Alt B */
10826 2, /* Alt PC to Alt B */
10827 3, /* PC to Alt B */
10828 4, /* Alt IC to Alt B */
10829 5, /* IC to Alt B */
10830 6, /* Alt B to Alt PC */
10831 7, /* B to Alt PC */
10832 8, /* Alt PC to Alt PC */
10833 9, /* PC to Alt PC */
10834 10, /* Alt IC to Alt PC */
10835 11, /* IC to Alt PC */
10836 12, /* Alt B to Alt IC */
10837 13, /* B to Alt IC */
10838 14, /* Alt PC to Alt IC */
10839 15, /* PC to Alt IC */
10840 16, /* Alt IC to Alt IC */
10841 17 /* IC to Alt IC */
10849 } xconnect_write_prog[] =
10851 { LI_COEF_CH_CH, FALSE, FALSE },
10852 { LI_COEF_CH_PC, FALSE, TRUE },
10853 { LI_COEF_PC_CH, TRUE, FALSE },
10854 { LI_COEF_PC_PC, TRUE, TRUE }
10858 static void xconnect_query_addresses (PLCI *plci)
10860 DIVA_CAPI_ADAPTER *a;
10864 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10865 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10866 (char *)(FILE_), __LINE__));
10869 if (a->li_pri && ((plci->li_bchannel_id == 0)
10870 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10872 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10873 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10874 (char *)(FILE_), __LINE__));
10877 p = plci->internal_req_buffer;
10878 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10879 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10882 *(p++) = (byte)(w >> 8);
10883 w = ch | XCONNECT_CHANNEL_PORT_PC;
10885 *(p++) = (byte)(w >> 8);
10886 plci->NData[0].P = plci->internal_req_buffer;
10887 plci->NData[0].PLength = p - plci->internal_req_buffer;
10888 plci->NL.X = plci->NData;
10889 plci->NL.ReqCh = 0;
10890 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10891 plci->adapter->request (&plci->NL);
10895 static void xconnect_write_coefs (PLCI *plci, word internal_command)
10898 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10899 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10900 (char *)(FILE_), __LINE__, internal_command));
10902 plci->li_write_command = internal_command;
10903 plci->li_write_channel = 0;
10907 static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10909 DIVA_CAPI_ADAPTER *a;
10910 word w, n, i, j, r, s, to_ch;
10913 struct xconnect_transfer_address_s *transfer_address;
10914 byte ch_map[MIXER_CHANNELS_BRI];
10916 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10917 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10920 if ((plci->li_bchannel_id == 0)
10921 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10923 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10924 UnMapId (Id), (char *)(FILE_), __LINE__));
10927 i = a->li_base + (plci->li_bchannel_id - 1);
10928 j = plci->li_write_channel;
10929 p = plci->internal_req_buffer;
10932 if ((Rc != OK) && (Rc != OK_FC))
10934 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10935 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10939 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10943 if (j < li_total_channels)
10945 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10947 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10948 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10949 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10950 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10952 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10953 while ((j < li_total_channels)
10955 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10956 || (!li_config_table[j].adapter->li_pri
10957 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10958 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10959 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10960 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10961 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10962 || ((li_config_table[j].adapter->li_base != a->li_base)
10964 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10965 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10966 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10967 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10970 if (j < li_total_channels)
10971 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10974 if (j < li_total_channels)
10976 plci->internal_command = plci->li_write_command;
10977 if (plci_nl_busy (plci))
10979 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10980 *(p++) = UDATA_REQUEST_XCONNECT_TO;
10983 if (li_config_table[j].adapter->li_base != a->li_base)
10986 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10987 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10988 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10989 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10994 if (r & xconnect_write_prog[n].mask)
10996 if (xconnect_write_prog[n].from_pc)
10997 transfer_address = &(li_config_table[j].send_pc);
10999 transfer_address = &(li_config_table[j].send_b);
11000 d = transfer_address->card_address.low;
11002 *(p++) = (byte)(d >> 8);
11003 *(p++) = (byte)(d >> 16);
11004 *(p++) = (byte)(d >> 24);
11005 d = transfer_address->card_address.high;
11007 *(p++) = (byte)(d >> 8);
11008 *(p++) = (byte)(d >> 16);
11009 *(p++) = (byte)(d >> 24);
11010 d = transfer_address->offset;
11012 *(p++) = (byte)(d >> 8);
11013 *(p++) = (byte)(d >> 16);
11014 *(p++) = (byte)(d >> 24);
11015 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11017 *(p++) = (byte)(w >> 8);
11018 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11019 (li_config_table[i].adapter->u_law ?
11020 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11021 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11024 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11027 } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11028 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11029 if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
11034 if (j < li_total_channels)
11035 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11036 } while ((j < li_total_channels)
11038 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11039 || (!li_config_table[j].adapter->li_pri
11040 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11041 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11042 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11043 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11044 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11045 || ((li_config_table[j].adapter->li_base != a->li_base)
11047 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11048 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11049 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11050 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11052 } while ((j < li_total_channels)
11053 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11055 else if (j == li_total_channels)
11057 plci->internal_command = plci->li_write_command;
11058 if (plci_nl_busy (plci))
11062 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11064 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11065 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11066 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11067 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11069 *(p++) = (byte)(w >> 8);
11073 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11075 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11076 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11078 w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11080 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11081 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11082 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11083 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11085 *(p++) = (byte)(w >> 8);
11086 for (j = 0; j < sizeof(ch_map); j += 2)
11088 if (plci->li_bchannel_id == 2)
11090 ch_map[j] = (byte)(j+1);
11091 ch_map[j+1] = (byte) j;
11095 ch_map[j] = (byte) j;
11096 ch_map[j+1] = (byte)(j+1);
11099 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11101 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11102 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11103 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11105 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11106 mixer_write_prog_bri[n].xconnect_override :
11107 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11108 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11110 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11111 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11117 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11119 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11120 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11121 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11127 j = li_total_channels + 1;
11132 if (j <= li_total_channels)
11134 plci->internal_command = plci->li_write_command;
11135 if (plci_nl_busy (plci))
11137 if (j < a->li_base)
11141 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11143 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11144 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11145 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11146 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11148 *(p++) = (byte)(w >> 8);
11149 for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++)
11151 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11152 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11154 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11155 if (w & mixer_write_prog_pri[n].mask)
11157 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11158 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11163 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11164 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11166 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11167 if (w & mixer_write_prog_pri[n].mask)
11169 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11170 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11179 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11181 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11182 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11184 w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11186 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11187 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11188 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11189 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11191 *(p++) = (byte)(w >> 8);
11192 for (j = 0; j < sizeof(ch_map); j += 2)
11194 if (plci->li_bchannel_id == 2)
11196 ch_map[j] = (byte)(j+1);
11197 ch_map[j+1] = (byte) j;
11201 ch_map[j] = (byte) j;
11202 ch_map[j+1] = (byte)(j+1);
11205 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
11207 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11208 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11209 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11211 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11212 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11213 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11218 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11220 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11221 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11222 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11228 j = li_total_channels + 1;
11231 plci->li_write_channel = j;
11232 if (p != plci->internal_req_buffer)
11234 plci->NData[0].P = plci->internal_req_buffer;
11235 plci->NData[0].PLength = p - plci->internal_req_buffer;
11236 plci->NL.X = plci->NData;
11237 plci->NL.ReqCh = 0;
11238 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11239 plci->adapter->request (&plci->NL);
11245 static void mixer_notify_update (PLCI *plci, byte others)
11247 DIVA_CAPI_ADAPTER *a;
11250 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11252 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11253 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11254 (char *)(FILE_), __LINE__, others));
11257 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11260 plci->li_notify_update = TRUE;
11264 notify_plci = NULL;
11267 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11269 if (i < li_total_channels)
11270 notify_plci = li_config_table[i++].plci;
11274 if ((plci->li_bchannel_id != 0)
11275 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11277 notify_plci = plci;
11280 if ((notify_plci != NULL)
11281 && !notify_plci->li_notify_update
11282 && (notify_plci->appl != NULL)
11283 && (notify_plci->State)
11284 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11286 notify_plci->li_notify_update = TRUE;
11287 ((CAPI_MSG *) msg)->header.length = 18;
11288 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11289 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11290 ((CAPI_MSG *) msg)->header.number = 0;
11291 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11292 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11293 ((CAPI_MSG *) msg)->header.ncci = 0;
11294 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11295 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11296 WRITE_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11297 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11298 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11299 if (w != _QUEUE_FULL)
11303 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11304 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11305 (char *)(FILE_), __LINE__,
11306 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11308 notify_plci->li_notify_update = FALSE;
11311 } while (others && (notify_plci != NULL));
11313 plci->li_notify_update = FALSE;
11318 static void mixer_clear_config (PLCI *plci)
11320 DIVA_CAPI_ADAPTER *a;
11323 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11324 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11325 (char *)(FILE_), __LINE__));
11327 plci->li_notify_update = FALSE;
11328 plci->li_plci_b_write_pos = 0;
11329 plci->li_plci_b_read_pos = 0;
11330 plci->li_plci_b_req_pos = 0;
11332 if ((plci->li_bchannel_id != 0)
11333 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11335 i = a->li_base + (plci->li_bchannel_id - 1);
11336 li_config_table[i].curchnl = 0;
11337 li_config_table[i].channel = 0;
11338 li_config_table[i].chflags = 0;
11339 for (j = 0; j < li_total_channels; j++)
11341 li_config_table[j].flag_table[i] = 0;
11342 li_config_table[i].flag_table[j] = 0;
11343 li_config_table[i].coef_table[j] = 0;
11344 li_config_table[j].coef_table[i] = 0;
11348 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11349 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11351 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11352 li_config_table[i].curchnl = 0;
11353 li_config_table[i].channel = 0;
11354 li_config_table[i].chflags = 0;
11355 for (j = 0; j < li_total_channels; j++)
11357 li_config_table[i].flag_table[j] = 0;
11358 li_config_table[j].flag_table[i] = 0;
11359 li_config_table[i].coef_table[j] = 0;
11360 li_config_table[j].coef_table[i] = 0;
11362 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11364 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11365 li_config_table[i].curchnl = 0;
11366 li_config_table[i].channel = 0;
11367 li_config_table[i].chflags = 0;
11368 for (j = 0; j < li_total_channels; j++)
11370 li_config_table[i].flag_table[j] = 0;
11371 li_config_table[j].flag_table[i] = 0;
11372 li_config_table[i].coef_table[j] = 0;
11373 li_config_table[j].coef_table[i] = 0;
11382 static void mixer_prepare_switch (dword Id, PLCI *plci)
11385 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11386 UnMapId (Id), (char *)(FILE_), __LINE__));
11390 mixer_indication_coefs_set (Id, plci);
11391 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11395 static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11397 DIVA_CAPI_ADAPTER *a;
11400 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11401 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11404 if ((plci->li_bchannel_id != 0)
11405 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11407 i = a->li_base + (plci->li_bchannel_id - 1);
11408 for (j = 0; j < li_total_channels; j++)
11410 li_config_table[i].coef_table[j] &= 0xf;
11411 li_config_table[j].coef_table[i] &= 0xf;
11414 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11420 static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11422 DIVA_CAPI_ADAPTER *a;
11425 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11426 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11430 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11431 && (plci->li_bchannel_id != 0)
11432 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11434 switch (plci->adjust_b_state)
11436 case ADJUST_B_RESTORE_MIXER_1:
11437 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11439 plci->internal_command = plci->adjust_b_command;
11440 if (plci_nl_busy (plci))
11442 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11445 xconnect_query_addresses (plci);
11446 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11449 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11451 case ADJUST_B_RESTORE_MIXER_2:
11452 case ADJUST_B_RESTORE_MIXER_3:
11453 case ADJUST_B_RESTORE_MIXER_4:
11454 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11456 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11457 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11458 Info = _WRONG_STATE;
11463 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11464 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11465 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11466 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11470 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11471 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11472 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11473 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11475 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11477 plci->internal_command = plci->adjust_b_command;
11480 case ADJUST_B_RESTORE_MIXER_5:
11481 xconnect_write_coefs (plci, plci->adjust_b_command);
11482 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11484 case ADJUST_B_RESTORE_MIXER_6:
11485 if (!xconnect_write_coefs_process (Id, plci, Rc))
11487 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11488 UnMapId (Id), (char *)(FILE_), __LINE__));
11489 Info = _FACILITY_NOT_SUPPORTED;
11492 if (plci->internal_command)
11494 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11495 case ADJUST_B_RESTORE_MIXER_7:
11503 static void mixer_command (dword Id, PLCI *plci, byte Rc)
11505 DIVA_CAPI_ADAPTER *a;
11506 word i, internal_command, Info;
11508 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11509 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11514 internal_command = plci->internal_command;
11515 plci->internal_command = 0;
11516 switch (plci->li_cmd)
11518 case LI_REQ_CONNECT:
11519 case LI_REQ_DISCONNECT:
11520 case LI_REQ_SILENT_UPDATE:
11521 switch (internal_command)
11524 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11526 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11527 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11529 case MIXER_COMMAND_1:
11530 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11532 if (adjust_b_process (Id, plci, Rc) != GOOD)
11534 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11535 UnMapId (Id), (char *)(FILE_), __LINE__));
11536 Info = _FACILITY_NOT_SUPPORTED;
11539 if (plci->internal_command)
11542 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11543 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11544 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11545 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11546 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11548 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11554 mixer_indication_coefs_set (Id, plci);
11555 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11557 case MIXER_COMMAND_2:
11558 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11559 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11560 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11561 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11563 if (!xconnect_write_coefs_process (Id, plci, Rc))
11565 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11566 UnMapId (Id), (char *)(FILE_), __LINE__));
11567 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11571 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11572 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11573 i = (plci->li_plci_b_write_pos == 0) ?
11574 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11575 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11576 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11578 Info = _FACILITY_NOT_SUPPORTED;
11581 if (plci->internal_command)
11584 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11586 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11587 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11589 case MIXER_COMMAND_3:
11590 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11592 if (adjust_b_process (Id, plci, Rc) != GOOD)
11594 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11595 UnMapId (Id), (char *)(FILE_), __LINE__));
11596 Info = _FACILITY_NOT_SUPPORTED;
11599 if (plci->internal_command)
11606 if ((plci->li_bchannel_id == 0)
11607 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11609 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11610 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11614 i = a->li_base + (plci->li_bchannel_id - 1);
11615 li_config_table[i].curchnl = plci->li_channel_bits;
11616 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11618 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11619 li_config_table[i].curchnl = plci->li_channel_bits;
11620 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11622 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11623 li_config_table[i].curchnl = plci->li_channel_bits;
11630 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11631 dword plci_b_id, byte connect, dword li_flags)
11633 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11635 DIVA_CAPI_ADAPTER *a_b;
11637 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11638 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11639 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11640 if (!a->li_pri && (plci->tel == ADV_VOICE)
11641 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11643 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11644 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11645 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11652 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11653 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11654 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11656 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11657 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11658 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11667 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11668 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11669 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11672 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11673 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11674 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11675 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11676 if (ch_a_v == ch_b_v)
11678 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11679 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11683 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11685 for (i = 0; i < li_total_channels; i++)
11688 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11691 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11693 for (i = 0; i < li_total_channels; i++)
11696 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11699 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11701 for (i = 0; i < li_total_channels; i++)
11704 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11707 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11709 for (i = 0; i < li_total_channels; i++)
11712 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11716 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11718 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11719 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11720 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11721 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11723 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11725 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11726 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11727 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11728 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11730 if (li_flags & LI_FLAG_MONITOR_A)
11732 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11733 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11735 if (li_flags & LI_FLAG_MONITOR_B)
11737 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11738 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11740 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11742 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11745 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11747 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11748 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750 if (li_flags & LI_FLAG_MIX_A)
11752 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11753 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11755 if (li_flags & LI_FLAG_MIX_B)
11757 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11758 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11760 if (ch_a_v != ch_a_s)
11762 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11763 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11765 if (ch_b_v != ch_b_s)
11767 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11768 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11773 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11774 dword plci_b_id, byte connect, dword li_flags)
11776 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11778 DIVA_CAPI_ADAPTER *a_b;
11780 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11781 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11782 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11783 if (!a->li_pri && (plci->tel == ADV_VOICE)
11784 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11786 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11787 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11788 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11795 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11796 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11797 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11799 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11800 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11801 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11810 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11811 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11812 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11813 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11814 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11815 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11817 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11827 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11828 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11829 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11830 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11832 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11834 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11835 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11836 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11837 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11839 if (li_flags & LI2_FLAG_MONITOR_B)
11841 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11842 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11844 if (li_flags & LI2_FLAG_MIX_B)
11846 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11847 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11849 if (li_flags & LI2_FLAG_MONITOR_X)
11850 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11851 if (li_flags & LI2_FLAG_MIX_X)
11852 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11853 if (li_flags & LI2_FLAG_LOOP_B)
11855 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11856 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11858 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11860 if (li_flags & LI2_FLAG_LOOP_PC)
11861 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11862 if (li_flags & LI2_FLAG_LOOP_X)
11863 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11864 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11865 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11866 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11867 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11868 if (ch_a_v != ch_a_s)
11870 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11871 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11873 if (ch_b_v != ch_b_s)
11875 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11876 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11881 static word li_check_main_plci (dword Id, PLCI *plci)
11885 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11886 UnMapId (Id), (char *)(FILE_), __LINE__));
11887 return (_WRONG_IDENTIFIER);
11890 || !plci->NL.Id || plci->nl_remove_id
11891 || (plci->li_bchannel_id == 0))
11893 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11894 UnMapId (Id), (char *)(FILE_), __LINE__));
11895 return (_WRONG_STATE);
11897 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11902 static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11903 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11908 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11909 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11911 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11912 UnMapId (Id), (char *)(FILE_), __LINE__));
11913 WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11917 if ((plci_b_id & 0x7f) != 0)
11919 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11920 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11924 || (((plci_b_id >> 8) & 0xff) == 0)
11925 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11927 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11928 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11929 WRITE_WORD (p_result, _WRONG_IDENTIFIER);
11932 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11934 || !plci_b->NL.Id || plci_b->nl_remove_id
11935 || (plci_b->li_bchannel_id == 0))
11937 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11938 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11939 WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11942 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11943 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11944 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11945 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11948 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11949 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11950 WRITE_WORD (p_result, _WRONG_IDENTIFIER);
11953 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11954 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11956 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11957 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11958 WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11965 static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11966 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11971 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11972 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11974 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11975 UnMapId (Id), (char *)(FILE_), __LINE__));
11976 WRITE_WORD (p_result, _WRONG_STATE);
11980 if ((plci_b_id & 0x7f) != 0)
11982 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11983 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11987 || (((plci_b_id >> 8) & 0xff) == 0)
11988 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11990 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11991 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11992 WRITE_WORD (p_result, _WRONG_IDENTIFIER);
11995 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11997 || !plci_b->NL.Id || plci_b->nl_remove_id
11998 || (plci_b->li_bchannel_id == 0)
11999 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12001 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12002 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12003 WRITE_WORD (p_result, _WRONG_STATE);
12006 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12007 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12008 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12009 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12011 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12012 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12013 WRITE_WORD (p_result, _WRONG_IDENTIFIER);
12016 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12017 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12019 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12020 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12021 WRITE_WORD (p_result, _WRONG_STATE);
12028 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12032 dword d, li_flags, plci_b_id;
12034 API_PARSE li_parms[3];
12035 API_PARSE li_req_parms[3];
12036 API_PARSE li_participant_struct[2];
12037 API_PARSE li_participant_parms[3];
12038 word participant_parms_pos;
12039 byte result_buffer[32];
12042 word plci_b_write_pos;
12044 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12045 UnMapId (Id), (char *)(FILE_), __LINE__));
12048 result = result_buffer;
12049 result_buffer[0] = 0;
12050 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12052 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12053 UnMapId (Id), (char *)(FILE_), __LINE__));
12054 Info = _FACILITY_NOT_SUPPORTED;
12056 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12058 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12059 UnMapId (Id), (char *)(FILE_), __LINE__));
12060 Info = _WRONG_MESSAGE_FORMAT;
12064 result_buffer[0] = 3;
12065 WRITE_WORD (&result_buffer[1], READ_WORD (li_parms[0].info));
12066 result_buffer[3] = 0;
12067 switch (READ_WORD (li_parms[0].info))
12069 case LI_GET_SUPPORTED_SERVICES:
12070 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12072 result_buffer[0] = 17;
12073 result_buffer[3] = 14;
12074 WRITE_WORD (&result_buffer[4], GOOD);
12076 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12077 d |= LI_CONFERENCING_SUPPORTED;
12078 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12079 d |= LI_MONITORING_SUPPORTED;
12080 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12081 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12082 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12083 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12084 WRITE_DWORD (&result_buffer[6], d);
12085 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12088 for (i = 0; i < li_total_channels; i++)
12090 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091 && (li_config_table[i].adapter->li_pri
12092 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12100 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12102 WRITE_DWORD (&result_buffer[10], d / 2);
12103 WRITE_DWORD (&result_buffer[14], d);
12107 result_buffer[0] = 25;
12108 result_buffer[3] = 22;
12109 WRITE_WORD (&result_buffer[4], GOOD);
12110 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12111 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12112 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12113 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12114 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12115 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12116 d |= LI2_PC_LOOPING_SUPPORTED;
12117 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12119 WRITE_DWORD (&result_buffer[6], d);
12120 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12121 WRITE_DWORD (&result_buffer[10], d / 2);
12122 WRITE_DWORD (&result_buffer[14], d - 1);
12123 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12126 for (i = 0; i < li_total_channels; i++)
12128 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12129 && (li_config_table[i].adapter->li_pri
12130 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12136 WRITE_DWORD (&result_buffer[18], d / 2);
12137 WRITE_DWORD (&result_buffer[22], d - 1);
12141 case LI_REQ_CONNECT:
12142 if (li_parms[1].length == 8)
12144 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12145 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12147 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12148 UnMapId (Id), (char *)(FILE_), __LINE__));
12149 Info = _WRONG_MESSAGE_FORMAT;
12152 plci_b_id = READ_DWORD (li_req_parms[0].info) & 0xffff;
12153 li_flags = READ_DWORD (li_req_parms[1].info);
12154 Info = li_check_main_plci (Id, plci);
12155 result_buffer[0] = 9;
12156 result_buffer[3] = 6;
12157 WRITE_DWORD (&result_buffer[4], plci_b_id);
12158 WRITE_WORD (&result_buffer[8], GOOD);
12161 result = plci->saved_msg.info;
12162 for (i = 0; i <= result_buffer[0]; i++)
12163 result[i] = result_buffer[i];
12164 plci_b_write_pos = plci->li_plci_b_write_pos;
12165 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12166 if (plci_b == NULL)
12168 li_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12169 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12170 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12171 plci->li_plci_b_write_pos = plci_b_write_pos;
12175 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12176 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12178 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12179 UnMapId (Id), (char *)(FILE_), __LINE__));
12180 Info = _WRONG_MESSAGE_FORMAT;
12183 li_flags = READ_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12184 Info = li_check_main_plci (Id, plci);
12185 result_buffer[0] = 7;
12186 result_buffer[3] = 4;
12187 WRITE_WORD (&result_buffer[4], Info);
12188 result_buffer[6] = 0;
12191 result = plci->saved_msg.info;
12192 for (i = 0; i <= result_buffer[0]; i++)
12193 result[i] = result_buffer[i];
12194 plci_b_write_pos = plci->li_plci_b_write_pos;
12195 participant_parms_pos = 0;
12197 li2_update_connect (Id, a, plci, UnMapId (Id), TRUE, li_flags);
12198 while (participant_parms_pos < li_req_parms[1].length)
12200 result[result_pos] = 6;
12202 WRITE_DWORD (&result[result_pos - 6], 0);
12203 WRITE_WORD (&result[result_pos - 2], GOOD);
12204 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12205 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12207 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12208 UnMapId (Id), (char *)(FILE_), __LINE__));
12209 WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12212 if (api_parse (&li_participant_struct[0].info[1],
12213 li_participant_struct[0].length, "dd", li_participant_parms))
12215 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12216 UnMapId (Id), (char *)(FILE_), __LINE__));
12217 WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12220 plci_b_id = READ_DWORD (li_participant_parms[0].info) & 0xffff;
12221 li_flags = READ_DWORD (li_participant_parms[1].info);
12222 WRITE_DWORD (&result[result_pos - 6], plci_b_id);
12223 if (sizeof(result) - result_pos < 7)
12225 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12226 UnMapId (Id), (char *)(FILE_), __LINE__));
12227 WRITE_WORD (&result[result_pos - 2], _WRONG_STATE);
12230 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12231 if (plci_b != NULL)
12233 li2_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
12234 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12235 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12236 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12237 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12239 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12240 (&li_req_parms[1].info[1]));
12242 result[0] = (byte)(result_pos - 1);
12243 result[3] = (byte)(result_pos - 4);
12244 result[6] = (byte)(result_pos - 7);
12245 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12246 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12247 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12249 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12250 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12253 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12254 plci->li_plci_b_write_pos = plci_b_write_pos;
12256 mixer_calculate_coefs (a);
12257 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12258 mixer_notify_update (plci, TRUE);
12259 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12260 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12262 plci->li_cmd = READ_WORD (li_parms[0].info);
12263 start_internal_command (Id, plci, mixer_command);
12266 case LI_REQ_DISCONNECT:
12267 if (li_parms[1].length == 4)
12269 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12270 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12272 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12273 UnMapId (Id), (char *)(FILE_), __LINE__));
12274 Info = _WRONG_MESSAGE_FORMAT;
12277 plci_b_id = READ_DWORD (li_req_parms[0].info) & 0xffff;
12278 Info = li_check_main_plci (Id, plci);
12279 result_buffer[0] = 9;
12280 result_buffer[3] = 6;
12281 WRITE_DWORD (&result_buffer[4], READ_DWORD (li_req_parms[0].info));
12282 WRITE_WORD (&result_buffer[8], GOOD);
12285 result = plci->saved_msg.info;
12286 for (i = 0; i <= result_buffer[0]; i++)
12287 result[i] = result_buffer[i];
12288 plci_b_write_pos = plci->li_plci_b_write_pos;
12289 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12290 if (plci_b == NULL)
12292 li_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12293 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12294 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12295 plci->li_plci_b_write_pos = plci_b_write_pos;
12299 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12300 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12302 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12303 UnMapId (Id), (char *)(FILE_), __LINE__));
12304 Info = _WRONG_MESSAGE_FORMAT;
12307 Info = li_check_main_plci (Id, plci);
12308 result_buffer[0] = 7;
12309 result_buffer[3] = 4;
12310 WRITE_WORD (&result_buffer[4], Info);
12311 result_buffer[6] = 0;
12314 result = plci->saved_msg.info;
12315 for (i = 0; i <= result_buffer[0]; i++)
12316 result[i] = result_buffer[i];
12317 plci_b_write_pos = plci->li_plci_b_write_pos;
12318 participant_parms_pos = 0;
12320 while (participant_parms_pos < li_req_parms[0].length)
12322 result[result_pos] = 6;
12324 WRITE_DWORD (&result[result_pos - 6], 0);
12325 WRITE_WORD (&result[result_pos - 2], GOOD);
12326 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12327 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12329 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12330 UnMapId (Id), (char *)(FILE_), __LINE__));
12331 WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12334 if (api_parse (&li_participant_struct[0].info[1],
12335 li_participant_struct[0].length, "d", li_participant_parms))
12337 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12338 UnMapId (Id), (char *)(FILE_), __LINE__));
12339 WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12342 plci_b_id = READ_DWORD (li_participant_parms[0].info) & 0xffff;
12343 WRITE_DWORD (&result[result_pos - 6], plci_b_id);
12344 if (sizeof(result) - result_pos < 7)
12346 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12347 UnMapId (Id), (char *)(FILE_), __LINE__));
12348 WRITE_WORD (&result[result_pos - 2], _WRONG_STATE);
12351 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12352 if (plci_b != NULL)
12354 li2_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
12355 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12356 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12358 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12359 (&li_req_parms[0].info[1]));
12361 result[0] = (byte)(result_pos - 1);
12362 result[3] = (byte)(result_pos - 4);
12363 result[6] = (byte)(result_pos - 7);
12364 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12365 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12366 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12368 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12369 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12372 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12373 plci->li_plci_b_write_pos = plci_b_write_pos;
12375 mixer_calculate_coefs (a);
12376 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12377 mixer_notify_update (plci, TRUE);
12378 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12379 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12381 plci->li_cmd = READ_WORD (li_parms[0].info);
12382 start_internal_command (Id, plci, mixer_command);
12385 case LI_REQ_SILENT_UPDATE:
12386 if (!plci || !plci->State
12387 || !plci->NL.Id || plci->nl_remove_id
12388 || (plci->li_bchannel_id == 0)
12389 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12391 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12392 UnMapId (Id), (char *)(FILE_), __LINE__));
12395 plci_b_write_pos = plci->li_plci_b_write_pos;
12396 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12397 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12399 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12400 UnMapId (Id), (char *)(FILE_), __LINE__));
12403 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12404 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12405 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12407 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12408 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12411 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12412 plci->li_plci_b_write_pos = plci_b_write_pos;
12413 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12415 plci->li_cmd = READ_WORD (li_parms[0].info);
12416 start_internal_command (Id, plci, mixer_command);
12420 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12421 UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (li_parms[0].info)));
12422 Info = _FACILITY_NOT_SUPPORTED;
12425 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12426 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12431 static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12434 DIVA_CAPI_ADAPTER *a;
12437 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12438 UnMapId (Id), (char *)(FILE_), __LINE__));
12441 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12445 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12446 if (!(d & LI_PLCI_B_SKIP_FLAG))
12448 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12450 if (d & LI_PLCI_B_DISC_FLAG)
12453 WRITE_WORD (&result[1], LI_IND_DISCONNECT);
12455 WRITE_WORD (&result[4], _LI_USER_INITIATED);
12460 WRITE_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12462 WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12467 if (d & LI_PLCI_B_DISC_FLAG)
12470 WRITE_WORD (&result[1], LI_IND_DISCONNECT);
12472 WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12473 WRITE_WORD (&result[8], _LI_USER_INITIATED);
12478 WRITE_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12480 WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12483 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12484 "ws", SELECTOR_LINE_INTERCONNECT, result);
12486 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12487 0 : plci->li_plci_b_read_pos + 1;
12488 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12493 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12496 struct xconnect_transfer_address_s s, *p;
12497 DIVA_CAPI_ADAPTER *a;
12499 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12500 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12504 for (i = 1; i < length; i += 16)
12506 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12507 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12508 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12509 ch = msg[i+12] | (msg[i+13] << 8);
12510 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12511 if (!a->li_pri && (plci->li_bchannel_id == 2))
12514 if (ch & XCONNECT_CHANNEL_PORT_PC)
12515 p = &(li_config_table[j].send_pc);
12517 p = &(li_config_table[j].send_b);
12518 p->card_address.low = s.card_address.low;
12519 p->card_address.high = s.card_address.high;
12520 p->offset = s.offset;
12521 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12523 if (plci->internal_command_queue[0]
12524 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12525 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12526 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12528 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12529 if (!plci->internal_command)
12530 next_internal_command (Id, plci);
12532 mixer_notify_update (plci, TRUE);
12536 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12539 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12540 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12545 static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12547 word plci_b_write_pos;
12549 plci_b_write_pos = plci->li_plci_b_write_pos;
12550 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12551 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12553 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12554 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12555 (char *)(FILE_), __LINE__));
12558 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12559 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12560 plci->li_plci_b_write_pos = plci_b_write_pos;
12565 static void mixer_remove (PLCI *plci)
12567 DIVA_CAPI_ADAPTER *a;
12572 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12573 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12574 (char *)(FILE_), __LINE__));
12577 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12578 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12580 if ((plci->li_bchannel_id != 0)
12581 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12583 i = a->li_base + (plci->li_bchannel_id - 1);
12584 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12586 for (j = 0; j < li_total_channels; j++)
12588 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12589 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12591 notify_plci = li_config_table[j].plci;
12592 if ((notify_plci != NULL)
12593 && (notify_plci != plci)
12594 && (notify_plci->appl != NULL)
12595 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12596 && (notify_plci->State)
12597 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12599 mixer_notify_source_removed (notify_plci, plci_b_id);
12603 mixer_clear_config (plci);
12604 mixer_calculate_coefs (a);
12605 mixer_notify_update (plci, TRUE);
12607 li_config_table[i].plci = NULL;
12608 plci->li_bchannel_id = 0;
12614 /*------------------------------------------------------------------*/
12615 /* Echo canceller facilities */
12616 /*------------------------------------------------------------------*/
12619 static void ec_write_parameters (PLCI *plci)
12622 byte parameter_buffer[6];
12624 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12625 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12626 (char *)(FILE_), __LINE__));
12628 parameter_buffer[0] = 5;
12629 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12630 WRITE_WORD (¶meter_buffer[2], plci->ec_idi_options);
12631 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12632 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12633 WRITE_WORD (¶meter_buffer[4], w);
12634 add_p (plci, FTY, parameter_buffer);
12635 sig_req (plci, TEL_CTRL, 0);
12640 static void ec_clear_config (PLCI *plci)
12643 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12644 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12645 (char *)(FILE_), __LINE__));
12647 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12648 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12649 plci->ec_tail_length = 0;
12653 static void ec_prepare_switch (dword Id, PLCI *plci)
12656 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12657 UnMapId (Id), (char *)(FILE_), __LINE__));
12662 static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12665 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12666 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672 static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12676 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12677 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12680 if (plci->B1_facilities & B1_FACILITY_EC)
12682 switch (plci->adjust_b_state)
12684 case ADJUST_B_RESTORE_EC_1:
12685 plci->internal_command = plci->adjust_b_command;
12688 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12691 ec_write_parameters (plci);
12692 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12694 case ADJUST_B_RESTORE_EC_2:
12695 if ((Rc != OK) && (Rc != OK_FC))
12697 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12698 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12699 Info = _WRONG_STATE;
12709 static void ec_command (dword Id, PLCI *plci, byte Rc)
12711 word internal_command, Info;
12714 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12715 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12716 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12719 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12722 WRITE_WORD (&result[1], EC_SUCCESS);
12727 WRITE_WORD (&result[1], plci->ec_cmd);
12729 WRITE_WORD (&result[4], GOOD);
12731 internal_command = plci->internal_command;
12732 plci->internal_command = 0;
12733 switch (plci->ec_cmd)
12735 case EC_ENABLE_OPERATION:
12736 case EC_FREEZE_COEFFICIENTS:
12737 case EC_RESUME_COEFFICIENT_UPDATE:
12738 case EC_RESET_COEFFICIENTS:
12739 switch (internal_command)
12742 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12743 B1_FACILITY_EC), EC_COMMAND_1);
12745 if (adjust_b_process (Id, plci, Rc) != GOOD)
12747 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12748 UnMapId (Id), (char *)(FILE_), __LINE__));
12749 Info = _FACILITY_NOT_SUPPORTED;
12752 if (plci->internal_command)
12757 plci->internal_command = EC_COMMAND_2;
12760 plci->internal_command = EC_COMMAND_3;
12761 ec_write_parameters (plci);
12764 if ((Rc != OK) && (Rc != OK_FC))
12766 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12767 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12768 Info = _FACILITY_NOT_SUPPORTED;
12775 case EC_DISABLE_OPERATION:
12776 switch (internal_command)
12780 if (plci->B1_facilities & B1_FACILITY_EC)
12784 plci->internal_command = EC_COMMAND_1;
12787 plci->internal_command = EC_COMMAND_2;
12788 ec_write_parameters (plci);
12793 if ((Rc != OK) && (Rc != OK_FC))
12795 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12796 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12797 Info = _FACILITY_NOT_SUPPORTED;
12800 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12801 ~B1_FACILITY_EC), EC_COMMAND_3);
12803 if (adjust_b_process (Id, plci, Rc) != GOOD)
12805 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12806 UnMapId (Id), (char *)(FILE_), __LINE__));
12807 Info = _FACILITY_NOT_SUPPORTED;
12810 if (plci->internal_command)
12816 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12817 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12818 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12822 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12826 API_PARSE ec_parms[3];
12829 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12830 UnMapId (Id), (char *)(FILE_), __LINE__));
12834 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12836 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12837 UnMapId (Id), (char *)(FILE_), __LINE__));
12838 Info = _FACILITY_NOT_SUPPORTED;
12842 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12844 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12846 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12847 UnMapId (Id), (char *)(FILE_), __LINE__));
12848 Info = _WRONG_MESSAGE_FORMAT;
12854 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12855 UnMapId (Id), (char *)(FILE_), __LINE__));
12856 Info = _WRONG_IDENTIFIER;
12858 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12860 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12861 UnMapId (Id), (char *)(FILE_), __LINE__));
12862 Info = _WRONG_STATE;
12867 plci->ec_cmd = READ_WORD (ec_parms[0].info);
12868 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12870 WRITE_WORD (&result[1], EC_SUCCESS);
12871 if (msg[1].length >= 4)
12873 opt = READ_WORD (&ec_parms[0].info[2]);
12874 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12875 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12876 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12877 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12878 if (opt & EC_DETECT_DISABLE_TONE)
12879 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12880 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12881 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12882 if (msg[1].length >= 6)
12884 plci->ec_tail_length = READ_WORD (&ec_parms[0].info[4]);
12887 switch (plci->ec_cmd)
12889 case EC_ENABLE_OPERATION:
12890 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12891 start_internal_command (Id, plci, ec_command);
12894 case EC_DISABLE_OPERATION:
12895 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12896 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12897 LEC_RESET_COEFFICIENTS;
12898 start_internal_command (Id, plci, ec_command);
12901 case EC_FREEZE_COEFFICIENTS:
12902 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12903 start_internal_command (Id, plci, ec_command);
12906 case EC_RESUME_COEFFICIENT_UPDATE:
12907 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12908 start_internal_command (Id, plci, ec_command);
12911 case EC_RESET_COEFFICIENTS:
12912 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12913 start_internal_command (Id, plci, ec_command);
12917 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12918 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12919 WRITE_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12926 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12928 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12929 UnMapId (Id), (char *)(FILE_), __LINE__));
12930 Info = _WRONG_MESSAGE_FORMAT;
12934 if (READ_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12937 WRITE_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12939 WRITE_WORD (&result[4], GOOD);
12940 WRITE_WORD (&result[6], 0x0007);
12941 WRITE_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12942 WRITE_WORD (&result[10], 0);
12944 else if (plci == NULL)
12946 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12947 UnMapId (Id), (char *)(FILE_), __LINE__));
12948 Info = _WRONG_IDENTIFIER;
12950 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12952 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12953 UnMapId (Id), (char *)(FILE_), __LINE__));
12954 Info = _WRONG_STATE;
12959 plci->ec_cmd = READ_WORD (ec_parms[0].info);
12960 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12962 WRITE_WORD (&result[1], plci->ec_cmd);
12964 WRITE_WORD (&result[4], GOOD);
12965 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12966 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12967 plci->ec_tail_length = 0;
12968 if (ec_parms[1].length >= 2)
12970 opt = READ_WORD (&ec_parms[1].info[1]);
12971 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12972 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12973 if (opt & EC_DETECT_DISABLE_TONE)
12974 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12975 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12976 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12977 if (ec_parms[1].length >= 4)
12979 plci->ec_tail_length = READ_WORD (&ec_parms[1].info[3]);
12982 switch (plci->ec_cmd)
12984 case EC_ENABLE_OPERATION:
12985 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12986 start_internal_command (Id, plci, ec_command);
12989 case EC_DISABLE_OPERATION:
12990 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12991 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12992 LEC_RESET_COEFFICIENTS;
12993 start_internal_command (Id, plci, ec_command);
12997 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12998 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12999 WRITE_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13005 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13006 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13007 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13012 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13016 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13017 UnMapId (Id), (char *)(FILE_), __LINE__));
13019 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13021 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13024 WRITE_WORD (&result[1], 0);
13027 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13028 WRITE_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13030 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13031 WRITE_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13033 case LEC_DISABLE_RELEASED:
13034 WRITE_WORD (&result[1], EC_BYPASS_RELEASED);
13041 WRITE_WORD (&result[1], EC_BYPASS_INDICATION);
13043 WRITE_WORD (&result[4], 0);
13046 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13047 WRITE_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13049 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13050 WRITE_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13052 case LEC_DISABLE_RELEASED:
13053 WRITE_WORD (&result[4], EC_BYPASS_RELEASED);
13057 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13058 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13064 /*------------------------------------------------------------------*/
13065 /* Advanced voice */
13066 /*------------------------------------------------------------------*/
13068 static void adv_voice_write_coefs (PLCI *plci, word write_command)
13070 DIVA_CAPI_ADAPTER *a;
13075 byte ch_map[MIXER_CHANNELS_BRI];
13077 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13079 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13080 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13081 (char *)(FILE_), __LINE__, write_command));
13084 p = coef_buffer + 1;
13085 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13087 while (i + sizeof(word) <= a->adv_voice_coef_length)
13089 WRITE_WORD (p, READ_WORD (a->adv_voice_coef_buffer + i));
13093 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13095 WRITE_WORD (p, 0x8000);
13100 if (!a->li_pri && (plci->li_bchannel_id == 0))
13102 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13104 plci->li_bchannel_id = 1;
13105 li_config_table[a->li_base].plci = plci;
13106 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13107 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13108 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13110 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13112 plci->li_bchannel_id = 2;
13113 li_config_table[a->li_base + 1].plci = plci;
13114 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13115 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13116 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13119 if (!a->li_pri && (plci->li_bchannel_id != 0)
13120 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13122 i = a->li_base + (plci->li_bchannel_id - 1);
13123 switch (write_command)
13125 case ADV_VOICE_WRITE_ACTIVATION:
13126 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13127 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13128 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13130 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13131 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13133 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13135 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13136 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13137 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13138 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13140 mixer_calculate_coefs (a);
13141 li_config_table[i].curchnl = li_config_table[i].channel;
13142 li_config_table[j].curchnl = li_config_table[j].channel;
13143 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13144 li_config_table[k].curchnl = li_config_table[k].channel;
13147 case ADV_VOICE_WRITE_DEACTIVATION:
13148 for (j = 0; j < li_total_channels; j++)
13150 li_config_table[i].flag_table[j] = 0;
13151 li_config_table[j].flag_table[i] = 0;
13153 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13154 for (j = 0; j < li_total_channels; j++)
13156 li_config_table[k].flag_table[j] = 0;
13157 li_config_table[j].flag_table[k] = 0;
13159 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13161 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13162 for (j = 0; j < li_total_channels; j++)
13164 li_config_table[k].flag_table[j] = 0;
13165 li_config_table[j].flag_table[k] = 0;
13168 mixer_calculate_coefs (a);
13171 if (plci->B1_facilities & B1_FACILITY_MIXER)
13174 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13175 w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13176 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13177 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13178 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13179 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13181 *(p++) = (byte)(w >> 8);
13182 for (j = 0; j < sizeof(ch_map); j += 2)
13184 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13185 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13187 for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
13189 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13190 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13191 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13193 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13194 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13195 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13199 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13200 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13206 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13207 *(p++) = a->adv_voice_coef_buffer[i];
13213 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13214 *(p++) = a->adv_voice_coef_buffer[i];
13216 coef_buffer[0] = (p - coef_buffer) - 1;
13217 add_p (plci, FTY, coef_buffer);
13218 sig_req (plci, TEL_CTRL, 0);
13223 static void adv_voice_clear_config (PLCI *plci)
13225 DIVA_CAPI_ADAPTER *a;
13230 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13231 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13232 (char *)(FILE_), __LINE__));
13235 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13237 a->adv_voice_coef_length = 0;
13239 if (!a->li_pri && (plci->li_bchannel_id != 0)
13240 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13242 i = a->li_base + (plci->li_bchannel_id - 1);
13243 li_config_table[i].curchnl = 0;
13244 li_config_table[i].channel = 0;
13245 li_config_table[i].chflags = 0;
13246 for (j = 0; j < li_total_channels; j++)
13248 li_config_table[i].flag_table[j] = 0;
13249 li_config_table[j].flag_table[i] = 0;
13250 li_config_table[i].coef_table[j] = 0;
13251 li_config_table[j].coef_table[i] = 0;
13253 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13254 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13255 li_config_table[i].curchnl = 0;
13256 li_config_table[i].channel = 0;
13257 li_config_table[i].chflags = 0;
13258 for (j = 0; j < li_total_channels; j++)
13260 li_config_table[i].flag_table[j] = 0;
13261 li_config_table[j].flag_table[i] = 0;
13262 li_config_table[i].coef_table[j] = 0;
13263 li_config_table[j].coef_table[i] = 0;
13265 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13267 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13268 li_config_table[i].curchnl = 0;
13269 li_config_table[i].channel = 0;
13270 li_config_table[i].chflags = 0;
13271 for (j = 0; j < li_total_channels; j++)
13273 li_config_table[i].flag_table[j] = 0;
13274 li_config_table[j].flag_table[i] = 0;
13275 li_config_table[i].coef_table[j] = 0;
13276 li_config_table[j].coef_table[i] = 0;
13285 static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13288 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13289 UnMapId (Id), (char *)(FILE_), __LINE__));
13294 static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13297 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13298 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13304 static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13306 DIVA_CAPI_ADAPTER *a;
13309 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13310 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13314 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13315 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13317 switch (plci->adjust_b_state)
13319 case ADJUST_B_RESTORE_VOICE_1:
13320 plci->internal_command = plci->adjust_b_command;
13323 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13326 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13327 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13329 case ADJUST_B_RESTORE_VOICE_2:
13330 if ((Rc != OK) && (Rc != OK_FC))
13332 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13333 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13334 Info = _WRONG_STATE;
13346 /*------------------------------------------------------------------*/
13347 /* B1 resource switching */
13348 /*------------------------------------------------------------------*/
13350 static byte b1_facilities_table[] =
13352 0x00, /* 0 No bchannel resources */
13353 0x00, /* 1 Codec (automatic law) */
13354 0x00, /* 2 Codec (A-law) */
13355 0x00, /* 3 Codec (y-law) */
13356 0x00, /* 4 HDLC for X.21 */
13358 0x00, /* 6 External Device 0 */
13359 0x00, /* 7 External Device 1 */
13360 0x00, /* 8 HDLC 56k */
13361 0x00, /* 9 Transparent */
13362 0x00, /* 10 Loopback to network */
13363 0x00, /* 11 Test pattern to net */
13364 0x00, /* 12 Rate adaptation sync */
13365 0x00, /* 13 Rate adaptation async */
13366 0x00, /* 14 R-Interface */
13367 0x00, /* 15 HDLC 128k leased line */
13369 0x00, /* 17 Modem async */
13370 0x00, /* 18 Modem sync HDLC */
13371 0x00, /* 19 V.110 async HDLC */
13372 0x12, /* 20 Adv voice (Trans,mixer) */
13373 0x00, /* 21 Codec connected to IC */
13374 0x0c, /* 22 Trans,DTMF */
13375 0x1e, /* 23 Trans,DTMF+mixer */
13376 0x1f, /* 24 Trans,DTMF+mixer+local */
13377 0x13, /* 25 Trans,mixer+local */
13378 0x12, /* 26 HDLC,mixer */
13379 0x12, /* 27 HDLC 56k,mixer */
13380 0x2c, /* 28 Trans,LEC+DTMF */
13381 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13382 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13383 0x2c, /* 31 RTP,LEC+DTMF */
13384 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13385 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13386 0x00, /* 34 Signaling task */
13387 0x00, /* 35 PIAFS */
13388 0x0c, /* 36 Trans,DTMF+TONE */
13389 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13390 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13394 static word get_b1_facilities (PLCI * plci, byte b1_resource)
13396 word b1_facilities;
13398 b1_facilities = b1_facilities_table[b1_resource];
13399 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13402 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13403 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13406 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13407 b1_facilities |= B1_FACILITY_DTMFX;
13408 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13409 b1_facilities |= B1_FACILITY_DTMFR;
13412 if ((b1_resource == 17) || (b1_resource == 18))
13414 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13415 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13418 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13419 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13420 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13422 return (b1_facilities);
13426 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13430 switch (b1_resource)
13434 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13442 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13460 if (b1_facilities & B1_FACILITY_EC)
13462 if (b1_facilities & B1_FACILITY_LOCAL)
13464 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13470 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13471 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13472 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13474 if (b1_facilities & B1_FACILITY_LOCAL)
13476 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13483 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13484 || ((b1_facilities & B1_FACILITY_DTMFR)
13485 && ((b1_facilities & B1_FACILITY_MIXER)
13486 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13487 || ((b1_facilities & B1_FACILITY_DTMFX)
13488 && ((b1_facilities & B1_FACILITY_MIXER)
13489 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13491 if (b1_facilities & B1_FACILITY_LOCAL)
13493 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13500 if (b1_facilities & B1_FACILITY_LOCAL)
13502 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13512 if (b1_facilities & B1_FACILITY_LOCAL)
13514 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13523 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13524 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13525 (char *)(FILE_), __LINE__,
13526 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13531 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13533 word removed_facilities;
13535 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13536 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13537 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13538 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13540 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13541 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13543 if (removed_facilities & B1_FACILITY_EC)
13544 ec_clear_config (plci);
13547 if (removed_facilities & B1_FACILITY_DTMFR)
13549 dtmf_rec_clear_config (plci);
13550 dtmf_parameter_clear_config (plci);
13552 if (removed_facilities & B1_FACILITY_DTMFX)
13553 dtmf_send_clear_config (plci);
13556 if (removed_facilities & B1_FACILITY_MIXER)
13557 mixer_clear_config (plci);
13559 if (removed_facilities & B1_FACILITY_VOICE)
13560 adv_voice_clear_config (plci);
13561 plci->B1_facilities = new_b1_facilities;
13565 static void adjust_b_clear (PLCI *plci)
13568 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13569 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13570 (char *)(FILE_), __LINE__));
13572 plci->adjust_b_restore = FALSE;
13576 static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13583 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13584 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13587 switch (plci->adjust_b_state)
13589 case ADJUST_B_START:
13590 if ((plci->adjust_b_parms_msg == NULL)
13591 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13592 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13593 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13595 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13596 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13597 if (b1_resource == plci->B1_resource)
13599 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13602 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13604 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13605 UnMapId (Id), (char *)(FILE_), __LINE__,
13606 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13607 Info = _WRONG_STATE;
13611 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13614 mixer_prepare_switch (Id, plci);
13617 dtmf_prepare_switch (Id, plci);
13618 dtmf_parameter_prepare_switch (Id, plci);
13621 ec_prepare_switch (Id, plci);
13623 adv_voice_prepare_switch (Id, plci);
13625 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13627 case ADJUST_B_SAVE_MIXER_1:
13628 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13631 Info = mixer_save_config (Id, plci, Rc);
13632 if ((Info != GOOD) || plci->internal_command)
13636 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13638 case ADJUST_B_SAVE_DTMF_1:
13639 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13642 Info = dtmf_save_config (Id, plci, Rc);
13643 if ((Info != GOOD) || plci->internal_command)
13647 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13648 case ADJUST_B_REMOVE_L23_1:
13649 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13650 && plci->NL.Id && !plci->nl_remove_id)
13652 plci->internal_command = plci->adjust_b_command;
13653 if (plci->adjust_b_ncci != 0)
13655 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13656 while (ncci_ptr->data_pending)
13658 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13659 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13661 while (ncci_ptr->data_ack_pending)
13662 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13664 nl_req_ncci (plci, REMOVE,
13665 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13667 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13670 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13672 case ADJUST_B_REMOVE_L23_2:
13673 if ((Rc != OK) && (Rc != OK_FC))
13675 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13676 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13677 Info = _WRONG_STATE;
13680 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13682 if (plci_nl_busy (plci))
13684 plci->internal_command = plci->adjust_b_command;
13688 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13690 case ADJUST_B_SAVE_EC_1:
13691 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13694 Info = ec_save_config (Id, plci, Rc);
13695 if ((Info != GOOD) || plci->internal_command)
13699 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13701 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13702 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13705 Info = dtmf_parameter_save_config (Id, plci, Rc);
13706 if ((Info != GOOD) || plci->internal_command)
13710 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13712 case ADJUST_B_SAVE_VOICE_1:
13713 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13715 Info = adv_voice_save_config (Id, plci, Rc);
13716 if ((Info != GOOD) || plci->internal_command)
13719 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13720 case ADJUST_B_SWITCH_L1_1:
13721 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13725 plci->internal_command = plci->adjust_b_command;
13728 if (plci->adjust_b_parms_msg != NULL)
13729 api_load_msg (plci->adjust_b_parms_msg, bp);
13731 api_load_msg (&plci->B_protocol, bp);
13732 Info = add_b1 (plci, bp,
13733 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13734 plci->adjust_b_facilities);
13737 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13738 UnMapId (Id), (char *)(FILE_), __LINE__,
13739 plci->B1_resource, plci->adjust_b_facilities));
13742 plci->internal_command = plci->adjust_b_command;
13743 sig_req (plci, RESOURCES, 0);
13745 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13748 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13750 case ADJUST_B_SWITCH_L1_2:
13751 if ((Rc != OK) && (Rc != OK_FC))
13753 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13754 UnMapId (Id), (char *)(FILE_), __LINE__,
13755 Rc, plci->B1_resource, plci->adjust_b_facilities));
13756 Info = _WRONG_STATE;
13759 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13761 case ADJUST_B_RESTORE_VOICE_1:
13762 case ADJUST_B_RESTORE_VOICE_2:
13763 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13765 Info = adv_voice_restore_config (Id, plci, Rc);
13766 if ((Info != GOOD) || plci->internal_command)
13769 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13771 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13772 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13773 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13776 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13777 if ((Info != GOOD) || plci->internal_command)
13781 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13783 case ADJUST_B_RESTORE_EC_1:
13784 case ADJUST_B_RESTORE_EC_2:
13785 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13788 Info = ec_restore_config (Id, plci, Rc);
13789 if ((Info != GOOD) || plci->internal_command)
13793 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13794 case ADJUST_B_ASSIGN_L23_1:
13795 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13797 if (plci_nl_busy (plci))
13799 plci->internal_command = plci->adjust_b_command;
13802 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13803 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13804 if (plci->adjust_b_parms_msg != NULL)
13805 api_load_msg (plci->adjust_b_parms_msg, bp);
13807 api_load_msg (&plci->B_protocol, bp);
13808 Info = add_b23 (plci, bp);
13811 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13812 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13815 plci->internal_command = plci->adjust_b_command;
13816 nl_req_ncci (plci, ASSIGN, 0);
13818 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13821 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13823 case ADJUST_B_ASSIGN_L23_2:
13824 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13826 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13827 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13828 Info = _WRONG_STATE;
13831 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13833 if (Rc != ASSIGN_OK)
13835 plci->internal_command = plci->adjust_b_command;
13839 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13841 plci->adjust_b_restore = TRUE;
13844 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13845 case ADJUST_B_CONNECT_1:
13846 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13848 plci->internal_command = plci->adjust_b_command;
13849 if (plci_nl_busy (plci))
13851 nl_req_ncci (plci, N_CONNECT, 0);
13853 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13856 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13858 case ADJUST_B_CONNECT_2:
13859 case ADJUST_B_CONNECT_3:
13860 case ADJUST_B_CONNECT_4:
13861 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13863 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13864 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13865 Info = _WRONG_STATE;
13870 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13872 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13873 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13875 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13876 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13877 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13878 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13882 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13883 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13884 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13885 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13887 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13889 plci->internal_command = plci->adjust_b_command;
13893 case ADJUST_B_RESTORE_DTMF_1:
13894 case ADJUST_B_RESTORE_DTMF_2:
13895 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13898 Info = dtmf_restore_config (Id, plci, Rc);
13899 if ((Info != GOOD) || plci->internal_command)
13903 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13905 case ADJUST_B_RESTORE_MIXER_1:
13906 case ADJUST_B_RESTORE_MIXER_2:
13907 case ADJUST_B_RESTORE_MIXER_3:
13908 case ADJUST_B_RESTORE_MIXER_4:
13909 case ADJUST_B_RESTORE_MIXER_5:
13910 case ADJUST_B_RESTORE_MIXER_6:
13911 case ADJUST_B_RESTORE_MIXER_7:
13912 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13915 Info = mixer_restore_config (Id, plci, Rc);
13916 if ((Info != GOOD) || plci->internal_command)
13920 plci->adjust_b_state = ADJUST_B_END;
13928 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13931 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13932 UnMapId (Id), (char *)(FILE_), __LINE__,
13933 plci->B1_resource, b1_facilities));
13935 plci->adjust_b_parms_msg = bp_msg;
13936 plci->adjust_b_facilities = b1_facilities;
13937 plci->adjust_b_command = internal_command;
13938 plci->adjust_b_ncci = (word)(Id >> 16);
13939 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13940 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13942 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13943 plci->adjust_b_state = ADJUST_B_START;
13944 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13945 UnMapId (Id), (char *)(FILE_), __LINE__,
13946 plci->B1_resource, b1_facilities));
13950 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13952 word internal_command;
13954 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13955 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13957 internal_command = plci->internal_command;
13958 plci->internal_command = 0;
13959 switch (internal_command)
13963 if (plci->req_in != 0)
13965 plci->internal_command = ADJUST_B_RESTORE_1;
13969 case ADJUST_B_RESTORE_1:
13970 if ((Rc != OK) && (Rc != OK_FC))
13972 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13973 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13975 plci->adjust_b_parms_msg = NULL;
13976 plci->adjust_b_facilities = plci->B1_facilities;
13977 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13978 plci->adjust_b_ncci = (word)(Id >> 16);
13979 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13980 plci->adjust_b_state = ADJUST_B_START;
13981 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13982 UnMapId (Id), (char *)(FILE_), __LINE__));
13983 case ADJUST_B_RESTORE_2:
13984 if (adjust_b_process (Id, plci, Rc) != GOOD)
13986 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13987 UnMapId (Id), (char *)(FILE_), __LINE__));
13989 if (plci->internal_command)
13996 static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
13999 word internal_command;
14001 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14002 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14005 internal_command = plci->internal_command;
14006 plci->internal_command = 0;
14007 switch (internal_command)
14011 plci->adjust_b_parms_msg = NULL;
14012 plci->adjust_b_facilities = plci->B1_facilities;
14013 plci->adjust_b_command = RESET_B3_COMMAND_1;
14014 plci->adjust_b_ncci = (word)(Id >> 16);
14015 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14016 plci->adjust_b_state = ADJUST_B_START;
14017 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14018 UnMapId (Id), (char *)(FILE_), __LINE__));
14019 case RESET_B3_COMMAND_1:
14020 Info = adjust_b_process (Id, plci, Rc);
14023 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14024 UnMapId (Id), (char *)(FILE_), __LINE__));
14027 if (plci->internal_command)
14031 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14032 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14036 static void select_b_command (dword Id, PLCI *plci, byte Rc)
14039 word internal_command;
14042 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14043 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14046 internal_command = plci->internal_command;
14047 plci->internal_command = 0;
14048 switch (internal_command)
14052 plci->adjust_b_parms_msg = &plci->saved_msg;
14053 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14054 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14056 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14057 plci->adjust_b_command = SELECT_B_COMMAND_1;
14058 plci->adjust_b_ncci = (word)(Id >> 16);
14059 if (plci->saved_msg.parms[0].length == 0)
14061 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14062 ADJUST_B_MODE_NO_RESOURCE;
14066 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14067 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14069 plci->adjust_b_state = ADJUST_B_START;
14070 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14071 UnMapId (Id), (char *)(FILE_), __LINE__));
14072 case SELECT_B_COMMAND_1:
14073 Info = adjust_b_process (Id, plci, Rc);
14076 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14077 UnMapId (Id), (char *)(FILE_), __LINE__));
14080 if (plci->internal_command)
14082 if (plci->tel == ADV_VOICE)
14086 esc_chi[2] = plci->b_channel;
14087 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14091 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14095 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14098 word internal_command;
14100 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14101 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14104 internal_command = plci->internal_command;
14105 plci->internal_command = 0;
14106 switch (internal_command)
14110 case FAX_CONNECT_ACK_COMMAND_1:
14111 if (plci_nl_busy (plci))
14113 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14116 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14117 plci->NData[0].P = plci->fax_connect_info_buffer;
14118 plci->NData[0].PLength = plci->fax_connect_info_length;
14119 plci->NL.X = plci->NData;
14120 plci->NL.ReqCh = 0;
14121 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14122 plci->adapter->request (&plci->NL);
14124 case FAX_CONNECT_ACK_COMMAND_2:
14125 if ((Rc != OK) && (Rc != OK_FC))
14127 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14128 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14132 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14133 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14135 if (plci->B3_prot == 4)
14136 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14138 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14139 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14144 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14147 word internal_command;
14149 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14150 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14153 internal_command = plci->internal_command;
14154 plci->internal_command = 0;
14155 switch (internal_command)
14159 case FAX_EDATA_ACK_COMMAND_1:
14160 if (plci_nl_busy (plci))
14162 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14165 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14166 plci->NData[0].P = plci->fax_connect_info_buffer;
14167 plci->NData[0].PLength = plci->fax_edata_ack_length;
14168 plci->NL.X = plci->NData;
14169 plci->NL.ReqCh = 0;
14170 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14171 plci->adapter->request (&plci->NL);
14173 case FAX_EDATA_ACK_COMMAND_2:
14174 if ((Rc != OK) && (Rc != OK_FC))
14176 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14177 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14184 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14187 word internal_command;
14189 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14190 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14193 internal_command = plci->internal_command;
14194 plci->internal_command = 0;
14195 switch (internal_command)
14199 case FAX_CONNECT_INFO_COMMAND_1:
14200 if (plci_nl_busy (plci))
14202 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14205 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14206 plci->NData[0].P = plci->fax_connect_info_buffer;
14207 plci->NData[0].PLength = plci->fax_connect_info_length;
14208 plci->NL.X = plci->NData;
14209 plci->NL.ReqCh = 0;
14210 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14211 plci->adapter->request (&plci->NL);
14213 case FAX_CONNECT_INFO_COMMAND_2:
14214 if ((Rc != OK) && (Rc != OK_FC))
14216 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14217 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14218 Info = _WRONG_STATE;
14221 if (plci_nl_busy (plci))
14223 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14226 plci->command = _CONNECT_B3_R;
14227 nl_req_ncci (plci, N_CONNECT, 0);
14231 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14235 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14238 word internal_command;
14240 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14241 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14244 internal_command = plci->internal_command;
14245 plci->internal_command = 0;
14246 switch (internal_command)
14250 plci->adjust_b_parms_msg = NULL;
14251 plci->adjust_b_facilities = plci->B1_facilities;
14252 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14253 plci->adjust_b_ncci = (word)(Id >> 16);
14254 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14255 plci->adjust_b_state = ADJUST_B_START;
14256 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14257 UnMapId (Id), (char *)(FILE_), __LINE__));
14258 case FAX_ADJUST_B23_COMMAND_1:
14259 Info = adjust_b_process (Id, plci, Rc);
14262 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14263 UnMapId (Id), (char *)(FILE_), __LINE__));
14266 if (plci->internal_command)
14268 case FAX_ADJUST_B23_COMMAND_2:
14269 if (plci_nl_busy (plci))
14271 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14274 plci->command = _CONNECT_B3_R;
14275 nl_req_ncci (plci, N_CONNECT, 0);
14279 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14283 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14285 word internal_command;
14287 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14288 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14290 internal_command = plci->internal_command;
14291 plci->internal_command = 0;
14292 switch (internal_command)
14296 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14298 case FAX_DISCONNECT_COMMAND_1:
14299 case FAX_DISCONNECT_COMMAND_2:
14300 case FAX_DISCONNECT_COMMAND_3:
14301 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14303 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14304 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14309 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14310 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14312 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14317 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14318 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14326 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14329 word internal_command;
14331 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14332 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14335 internal_command = plci->internal_command;
14336 plci->internal_command = 0;
14337 switch (internal_command)
14341 case RTP_CONNECT_B3_REQ_COMMAND_1:
14342 if (plci_nl_busy (plci))
14344 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14347 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14348 nl_req_ncci (plci, N_CONNECT, 0);
14351 case RTP_CONNECT_B3_REQ_COMMAND_2:
14352 if ((Rc != OK) && (Rc != OK_FC))
14354 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14355 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14356 Info = _WRONG_STATE;
14359 if (plci_nl_busy (plci))
14361 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14364 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14365 plci->NData[0].PLength = plci->internal_req_buffer[0];
14366 plci->NData[0].P = plci->internal_req_buffer + 1;
14367 plci->NL.X = plci->NData;
14368 plci->NL.ReqCh = 0;
14369 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14370 plci->adapter->request (&plci->NL);
14372 case RTP_CONNECT_B3_REQ_COMMAND_3:
14375 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14379 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14382 word internal_command;
14384 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14385 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14388 internal_command = plci->internal_command;
14389 plci->internal_command = 0;
14390 switch (internal_command)
14394 case RTP_CONNECT_B3_RES_COMMAND_1:
14395 if (plci_nl_busy (plci))
14397 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14400 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14401 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14404 case RTP_CONNECT_B3_RES_COMMAND_2:
14405 if ((Rc != OK) && (Rc != OK_FC))
14407 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14408 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14409 Info = _WRONG_STATE;
14412 if (plci_nl_busy (plci))
14414 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14417 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14418 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14419 plci->NData[0].PLength = plci->internal_req_buffer[0];
14420 plci->NData[0].P = plci->internal_req_buffer + 1;
14421 plci->NL.X = plci->NData;
14422 plci->NL.ReqCh = 0;
14423 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14424 plci->adapter->request (&plci->NL);
14426 case RTP_CONNECT_B3_RES_COMMAND_3:
14433 static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14435 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14437 word internal_command;
14439 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14440 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14443 internal_command = plci->internal_command;
14444 plci->internal_command = 0;
14445 switch (internal_command)
14451 plci->adjust_b_parms_msg = NULL;
14452 plci->adjust_b_facilities = plci->B1_facilities;
14453 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14454 plci->adjust_b_ncci = (word)(Id >> 16);
14455 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14456 plci->adjust_b_state = ADJUST_B_START;
14457 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14458 UnMapId (Id), (char *)(FILE_), __LINE__));
14459 case HOLD_SAVE_COMMAND_1:
14460 Info = adjust_b_process (Id, plci, Rc);
14463 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14464 UnMapId (Id), (char *)(FILE_), __LINE__));
14467 if (plci->internal_command)
14470 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14474 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14476 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14478 word internal_command;
14480 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14481 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14484 internal_command = plci->internal_command;
14485 plci->internal_command = 0;
14486 switch (internal_command)
14490 plci->adjust_b_parms_msg = NULL;
14491 plci->adjust_b_facilities = plci->B1_facilities;
14492 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14493 plci->adjust_b_ncci = (word)(Id >> 16);
14494 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14495 plci->adjust_b_state = ADJUST_B_START;
14496 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14497 UnMapId (Id), (char *)(FILE_), __LINE__));
14498 case RETRIEVE_RESTORE_COMMAND_1:
14499 Info = adjust_b_process (Id, plci, Rc);
14502 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14503 UnMapId (Id), (char *)(FILE_), __LINE__));
14506 if (plci->internal_command)
14509 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14513 static void init_b1_config (PLCI *plci)
14516 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14517 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14518 (char *)(FILE_), __LINE__));
14520 plci->B1_resource = 0;
14521 plci->B1_facilities = 0;
14523 plci->li_bchannel_id = 0;
14524 mixer_clear_config (plci);
14527 ec_clear_config (plci);
14530 dtmf_rec_clear_config (plci);
14531 dtmf_send_clear_config (plci);
14532 dtmf_parameter_clear_config (plci);
14534 adv_voice_clear_config (plci);
14535 adjust_b_clear (plci);
14539 static void clear_b1_config (PLCI *plci)
14542 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14543 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14544 (char *)(FILE_), __LINE__));
14546 adv_voice_clear_config (plci);
14547 adjust_b_clear (plci);
14549 ec_clear_config (plci);
14552 dtmf_rec_clear_config (plci);
14553 dtmf_send_clear_config (plci);
14554 dtmf_parameter_clear_config (plci);
14557 if ((plci->li_bchannel_id != 0)
14558 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14560 mixer_clear_config (plci);
14561 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14562 plci->li_bchannel_id = 0;
14565 plci->B1_resource = 0;
14566 plci->B1_facilities = 0;
14570 /* -----------------------------------------------------------------
14571 XON protocol local helpers
14572 ----------------------------------------------------------------- */
14573 static void channel_flow_control_remove (PLCI * plci) {
14574 DIVA_CAPI_ADAPTER * a = plci->adapter;
14576 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14577 if (a->ch_flow_plci[i] == plci->Id) {
14578 a->ch_flow_plci[i] = 0;
14579 a->ch_flow_control[i] = 0;
14584 static void channel_x_on (PLCI * plci, byte ch) {
14585 DIVA_CAPI_ADAPTER * a = plci->adapter;
14586 if (a->ch_flow_control[ch] & N_XON_SENT) {
14587 a->ch_flow_control[ch] &= ~N_XON_SENT;
14591 static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14592 DIVA_CAPI_ADAPTER * a = plci->adapter;
14593 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14594 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14595 a->ch_flow_plci[ch] = plci->Id;
14596 a->ch_flow_control_pending++;
14600 static void channel_request_xon (PLCI * plci, byte ch) {
14601 DIVA_CAPI_ADAPTER * a = plci->adapter;
14603 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14604 a->ch_flow_control[ch] |= N_XON_REQ;
14605 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14606 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14610 static void channel_xmit_extended_xon (PLCI * plci) {
14611 DIVA_CAPI_ADAPTER * a;
14612 int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14613 int i, one_requested = 0;
14615 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14619 for (i = 0; i < max_ch; i++) {
14620 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14621 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14622 (plci->Id == a->ch_flow_plci[i])) {
14623 channel_request_xon (plci, (byte)i);
14628 if (one_requested) {
14629 channel_xmit_xon (plci);
14634 Try to xmit next X_ON
14636 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14637 int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
14640 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14644 if (a->last_flow_control_ch >= max_ch) {
14645 a->last_flow_control_ch = 1;
14647 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14648 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649 (plci->Id == a->ch_flow_plci[i])) {
14650 a->last_flow_control_ch = i+1;
14655 for (i = 1; i < a->last_flow_control_ch; i++) {
14656 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14657 (plci->Id == a->ch_flow_plci[i])) {
14658 a->last_flow_control_ch = i+1;
14666 static void channel_xmit_xon (PLCI * plci) {
14667 DIVA_CAPI_ADAPTER * a = plci->adapter;
14670 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14673 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14676 a->ch_flow_control[ch] &= ~N_XON_REQ;
14677 a->ch_flow_control[ch] |= N_XON_SENT;
14679 plci->NL.Req = plci->nl_req = (byte)N_XON;
14680 plci->NL.ReqCh = ch;
14681 plci->NL.X = plci->NData;
14683 plci->NData[0].P = &plci->RBuffer[0];
14684 plci->NData[0].PLength = 0;
14686 plci->adapter->request(&plci->NL);
14689 static int channel_can_xon (PLCI * plci, byte ch) {
14691 DIVA_CAPI_ADAPTER * a;
14697 APPLptr = plci->appl;
14703 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14705 /* count all buffers within the Application pool */
14706 /* belonging to the same NCCI. XON if a first is */
14710 for(i=0; i<APPLptr->MaxBuffer; i++) {
14711 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14712 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14714 if ((count > 2) || (Num == 0xffff)) {
14721 /*------------------------------------------------------------------*/
14723 /* to be completed */
14724 void disable_adapter(byte adapter_number)
14727 DIVA_CAPI_ADAPTER *a;
14731 if ((adapter_number == 0) || (adapter_number > max_adapter) || !adapter[adapter_number-1].request)
14733 dbug(1,dprintf("disable adapter: number %d invalid",adapter_number));
14736 dbug(1,dprintf("disable adapter number %d",adapter_number));
14737 /* Capi20 starts with Nr. 1, internal field starts with 0 */
14738 a = &adapter[adapter_number-1];
14739 a->adapter_disabled = TRUE;
14740 for(j=0;j<a->max_plci;j++)
14742 if(a->plci[j].Id) /* disconnect logical links */
14744 plci = &a->plci[j];
14747 for(ncci=1;ncci<MAX_NCCI+1 && plci->channels;ncci++)
14749 if(a->ncci_plci[ncci]==plci->Id)
14751 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
14752 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"ws",0,"");
14758 if(plci->State!=LISTENING) /* disconnect physical links */
14760 Id = ((word)plci->Id<<8)|a->Id;
14761 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
14771 void enable_adapter(byte adapter_number)
14773 DIVA_CAPI_ADAPTER *a;
14775 if ((adapter_number == 0) || (adapter_number > max_adapter) || !adapter[adapter_number-1].request)
14777 dbug(1,dprintf("enable adapter: number %d invalid",adapter_number));
14780 dbug(1,dprintf("enable adapter number %d",adapter_number));
14781 /* Capi20 starts with Nr. 1, internal field starts with 0 */
14782 a = &adapter[adapter_number-1];
14783 a->adapter_disabled = FALSE;
14788 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14795 /**********************************************************************************/
14796 /* function groups the listening applications according to the CIP mask and the */
14797 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14798 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14799 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14800 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14801 /* OS specific part (per adapter). */
14802 /**********************************************************************************/
14803 void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14805 word i,j,k,busy,group_found;
14806 dword info_mask_group[MAX_CIP_TYPES];
14807 dword cip_mask_group[MAX_CIP_TYPES];
14808 word appl_number_group_type[MAX_APPL];
14811 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14813 if(!a->group_optimization_enabled)
14815 dbug(1,dprintf("No group optimization"));
14819 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14821 for(i=0;i<MAX_CIP_TYPES;i++)
14823 info_mask_group[i] = 0;
14824 cip_mask_group [i] = 0;
14826 for(i=0;i<MAX_APPL;i++)
14828 appl_number_group_type[i] = 0;
14830 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14831 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14832 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14834 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14835 return; /* allow good application unfiltered access */
14838 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14840 if(application[i].Id && a->CIP_Mask[i] )
14842 for(k=0,busy=FALSE; k<a->max_plci; k++)
14846 auxplci = &a->plci[k];
14847 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14850 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14852 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14855 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14860 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14862 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14863 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14864 appl_number_group_type[i] = MAX_CIP_TYPES;
14866 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14868 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14869 { /* is group already present ? */
14870 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14872 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]));
14874 else if(!info_mask_group[j])
14875 { /* establish a new group */
14876 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14877 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14878 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14880 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]));
14886 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14888 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14890 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14892 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14896 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14897 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14899 if(appl_number_group_type[i] == appl_number_group_type[j])
14901 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14902 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14903 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14908 else /* application should not get a call */
14910 clear_group_ind_mask_bit (plci, i);
14918 /* OS notifies the driver about a application Capi_Register */
14919 word CapiRegister(word id)
14921 word i,j,appls_found;
14924 DIVA_CAPI_ADAPTER *a;
14926 for(i=0,appls_found=0; i<max_appl; i++)
14928 if( application[i].Id && (application[i].Id!=id) )
14930 appls_found++; /* an application has been found */
14934 if(appls_found) return TRUE;
14935 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14940 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14942 if(!appls_found) /* first application does a capi register */
14944 if((j=get_plci(a))) /* activate L1 of all adapters */
14946 plci = &a->plci[j-1];
14948 add_p(plci,OAD,"\x01\xfd");
14949 add_p(plci,CAI,"\x01\x80");
14950 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14951 add_p(plci,SHIFT|6,NULL);
14952 add_p(plci,SIN,"\x02\x00\x00");
14953 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14954 sig_req(plci,ASSIGN,DSIG_ID);
14955 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14956 sig_req(plci,SIG_CTRL,0);
14966 /*------------------------------------------------------------------*/
14968 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14970 void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14973 /* Format of vswitch_t:
14976 2 byte VSWITCH_REQ/VSWITCH_IND
14978 4 word VSwitchcommand
14985 plci->Sig.Ind==NCR_FACILITY
14989 for(i=0;i<MAX_MULTI_IE;i++)
14991 if(!parms[i][0]) continue;
14994 parms[i][0]=0; /* kill it */
14997 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14998 switch(parms[i][4])
15001 if(!plci->relatedPTYPLCI ||
15002 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
15006 /* remember all necessary informations */
15007 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
15011 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
15012 { /* first indication after ECT-Request on Consultation Call */
15013 plci->vswitchstate=parms[i][9];
15014 parms[i][9]=2; /* State */
15015 /* now ask first Call to join */
15017 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
15018 { /* Answer of VSWITCH_REQ from first Call */
15019 plci->vswitchstate=parms[i][9];
15020 /* tell consultation call to join
15021 and the protocol capabilities of the first call */
15027 plci->vsprot=parms[i][10]; /* protocol */
15028 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
15029 /* send join request to related PLCI */
15030 parms[i][1]=VSWITCHIE;
15031 parms[i][2]=VSWITCH_REQ;
15033 plci->relatedPTYPLCI->command = 0;
15034 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
15035 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
15036 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15037 send_req(plci->relatedPTYPLCI);
15041 if(plci->relatedPTYPLCI &&
15042 plci->vswitchstate==3 &&
15043 plci->relatedPTYPLCI->vswitchstate==3)
15045 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
15046 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15047 send_req(plci->relatedPTYPLCI);
15051 parms[i][0]=0; /* kill it */
15056 /*------------------------------------------------------------------*/
15058 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
15060 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15062 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15066 pReq->xdi_dma_descriptor_operation.Req = 0;
15067 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15069 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15070 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15071 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15072 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15074 e.user[0] = plci->adapter->Id - 1;
15075 plci->adapter->request((ENTITY*)pReq);
15077 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15078 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15079 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15080 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15081 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15083 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15085 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15087 dbug(1,dprintf("dma_alloc failed"));
15092 static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15094 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15100 pReq->xdi_dma_descriptor_operation.Req = 0;
15101 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15103 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15104 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15105 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15106 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15108 e.user[0] = plci->adapter->Id - 1;
15109 plci->adapter->request((ENTITY*)pReq);
15111 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15112 dbug(1,dprintf("dma_free(%d)", nr));
15114 dbug(1,dprintf("dma_free failed (%d)", nr));
15118 /*------------------------------------------------------------------*/