3 Copyright (c) Eicon Networks, 2002.
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
8 Eicon File Revision : 2.1
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40 #define FILE_ "MESSAGE.C"
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter */
55 /* Macrose defined here have only local meaning */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
59 #define DIVA_CAPI_USE_CMA 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR 0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL 0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA 0x00000008
65 CAPI can request to process all return codes self only if:
66 protocol code supports this && xdi supports this
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__) (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&& ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
70 /*------------------------------------------------------------------*/
71 /* local function prototypes */
72 /*------------------------------------------------------------------*/
74 static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci);
75 static void set_group_ind_mask (PLCI *plci);
76 static void clear_group_ind_mask_bit (PLCI *plci, word b);
77 static byte test_group_ind_mask_bit (PLCI *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL *, CAPI_MSG *);
82 static word api_parse(byte *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84 static void api_load_msg(API_SAVE *in, API_PARSE *out);
86 word api_remove_start(void);
87 void api_remove_complete(void);
89 static void plci_remove(PLCI *);
90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a);
91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
93 void callback(ENTITY *);
95 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI *, byte);
97 static void data_ack(PLCI *, byte);
98 static void sig_ind(PLCI *);
99 static void SendInfo(PLCI *, dword, byte * *, byte);
100 static void SendSetupInfo(APPL *, PLCI *, dword, byte * *, byte);
101 static void SendSSExtInd(APPL *, PLCI * plci, dword Id, byte * * parms);
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
105 static void nl_ind(PLCI *);
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
132 static word get_plci(DIVA_CAPI_ADAPTER *);
133 static void add_p(PLCI *, byte, byte *);
134 static void add_s(PLCI * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI * plci, byte code, byte * p, word p_length);
137 static void add_d(PLCI *, word, byte *);
138 static void add_ai(PLCI *, API_PARSE *);
139 static word add_b1(PLCI *, API_PARSE *, word, word);
140 static word add_b23(PLCI *, API_PARSE *);
141 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI *, byte, byte);
143 static void nl_req_ncci(PLCI *, byte, byte);
144 static void send_req(PLCI *);
145 static void send_data(PLCI *);
146 static word plci_remove_check(PLCI *);
147 static void listen_check(DIVA_CAPI_ADAPTER *);
148 static byte AddInfo(byte **, byte **, byte *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI *, word *, byte **, byte);
151 static byte ie_compare(byte *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER *,word);
158 static void channel_flow_control_remove (PLCI * plci);
159 static void channel_x_off (PLCI * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI * plci, byte ch);
161 static void channel_request_xon (PLCI * plci, byte ch);
162 static void channel_xmit_xon (PLCI * plci);
163 static int channel_can_xon (PLCI * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI * plci);
166 static byte SendMultiIE(PLCI * plci, dword Id, byte * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER * );
170 static void VoiceChannelOff(PLCI *plci);
171 static void adv_voice_write_coefs (PLCI *plci, word write_command);
172 static void adv_voice_clear_config (PLCI *plci);
174 static word get_b1_facilities (PLCI * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc);
189 static void init_b1_config (PLCI *plci);
190 static void clear_b1_config (PLCI *plci);
192 static void dtmf_command (dword Id, PLCI *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI *plci);
195 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length);
196 static void dtmf_parameter_write (PLCI *plci);
199 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI *plci, byte *chi);
201 static void mixer_clear_config (PLCI *plci);
202 static void mixer_notify_update (PLCI *plci, byte others);
203 static void mixer_command (dword Id, PLCI *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_remove (PLCI *plci);
211 static void ec_command (dword Id, PLCI *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length);
216 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc);
220 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor (PLCI *plci, int nr);
223 /*------------------------------------------------------------------*/
224 /* external function prototypes */
225 /*------------------------------------------------------------------*/
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
232 void sendf(APPL *, word, dword, word, byte *, ...);
233 void * TransmitBufferSet(APPL * appl, dword ref);
234 void * TransmitBufferGet(APPL * appl, void * p);
235 void TransmitBufferFree(APPL * appl, void * p);
236 void * ReceiveBufferGet(APPL * appl, int Num);
238 int fax_head_line_time (char *buffer);
241 /*------------------------------------------------------------------*/
242 /* Global data definitions */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER * adapter;
247 extern APPL * application;
255 static byte remove_started = false;
256 static PLCI dummy_plci;
259 static struct _ftable {
262 byte (* function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
264 {_DATA_B3_R, "dwww", data_b3_req},
265 {_DATA_B3_I|RESPONSE, "w", data_b3_res},
266 {_INFO_R, "ss", info_req},
267 {_INFO_I|RESPONSE, "", info_res},
268 {_CONNECT_R, "wsssssssss", connect_req},
269 {_CONNECT_I|RESPONSE, "wsssss", connect_res},
270 {_CONNECT_ACTIVE_I|RESPONSE, "", connect_a_res},
271 {_DISCONNECT_R, "s", disconnect_req},
272 {_DISCONNECT_I|RESPONSE, "", disconnect_res},
273 {_LISTEN_R, "dddss", listen_req},
274 {_ALERT_R, "s", alert_req},
275 {_FACILITY_R, "ws", facility_req},
276 {_FACILITY_I|RESPONSE, "ws", facility_res},
277 {_CONNECT_B3_R, "s", connect_b3_req},
278 {_CONNECT_B3_I|RESPONSE, "ws", connect_b3_res},
279 {_CONNECT_B3_ACTIVE_I|RESPONSE, "", connect_b3_a_res},
280 {_DISCONNECT_B3_R, "s", disconnect_b3_req},
281 {_DISCONNECT_B3_I|RESPONSE, "", disconnect_b3_res},
282 {_RESET_B3_R, "s", reset_b3_req},
283 {_RESET_B3_I|RESPONSE, "", reset_b3_res},
284 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "ws", connect_b3_t90_a_res},
285 {_CONNECT_B3_T90_ACTIVE_I|RESPONSE, "", connect_b3_t90_a_res},
286 {_SELECT_B_REQ, "s", select_b_req},
287 {_MANUFACTURER_R, "dws", manufacturer_req},
288 {_MANUFACTURER_I|RESPONSE, "dws", manufacturer_res},
289 {_MANUFACTURER_I|RESPONSE, "", manufacturer_res}
292 static byte * cip_bc[29][2] = {
294 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 1 */
295 { "\x02\x88\x90", "\x02\x88\x90" }, /* 2 */
296 { "\x02\x89\x90", "\x02\x89\x90" }, /* 3 */
297 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 4 */
298 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 5 */
299 { "\x02\x98\x90", "\x02\x98\x90" }, /* 6 */
300 { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301 { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 9 */
310 { "\x03\x80\x90\xa3", "\x03\x80\x90\xa2" }, /* 16 */
311 { "\x03\x90\x90\xa3", "\x03\x90\x90\xa2" }, /* 17 */
312 { "\x02\x88\x90", "\x02\x88\x90" }, /* 18 */
313 { "\x02\x88\x90", "\x02\x88\x90" }, /* 19 */
314 { "\x02\x88\x90", "\x02\x88\x90" }, /* 20 */
315 { "\x02\x88\x90", "\x02\x88\x90" }, /* 21 */
316 { "\x02\x88\x90", "\x02\x88\x90" }, /* 22 */
317 { "\x02\x88\x90", "\x02\x88\x90" }, /* 23 */
318 { "\x02\x88\x90", "\x02\x88\x90" }, /* 24 */
319 { "\x02\x88\x90", "\x02\x88\x90" }, /* 25 */
320 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 26 */
321 { "\x03\x91\x90\xa5", "\x03\x91\x90\xa5" }, /* 27 */
322 { "\x02\x88\x90", "\x02\x88\x90" } /* 28 */
325 static byte * cip_hlc[29] = {
343 "\x02\x91\x81", /* 16 */
344 "\x02\x91\x84", /* 17 */
345 "\x02\x91\xa1", /* 18 */
346 "\x02\x91\xa4", /* 19 */
347 "\x02\x91\xa8", /* 20 */
348 "\x02\x91\xb1", /* 21 */
349 "\x02\x91\xb2", /* 22 */
350 "\x02\x91\xb5", /* 23 */
351 "\x02\x91\xb8", /* 24 */
352 "\x02\x91\xc1", /* 25 */
353 "\x02\x91\x81", /* 26 */
354 "\x03\x91\xe0\x01", /* 27 */
355 "\x03\x91\xe0\x02" /* 28 */
358 /*------------------------------------------------------------------*/
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT 0x80
362 #define V120_HEADER_BREAK_BIT 0x40
363 #define V120_HEADER_C1_BIT 0x04
364 #define V120_HEADER_C2_BIT 0x08
365 #define V120_HEADER_FLUSH_COND (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
367 static byte v120_default_header[] =
370 0x83 /* Ext, BR , res, res, C2 , C1 , B , F */
374 static byte v120_break_header[] =
377 0xc3 | V120_HEADER_BREAK_BIT /* Ext, BR , res, res, C2 , C1 , B , F */
382 /*------------------------------------------------------------------*/
383 /* API_PUT function */
384 /*------------------------------------------------------------------*/
386 word api_put(APPL * appl, CAPI_MSG * msg)
392 DIVA_CAPI_ADAPTER * a;
397 API_PARSE msg_parms[MAX_MSG_PARMS+1];
399 if (msg->header.length < sizeof (msg->header) ||
400 msg->header.length > MAX_MSG_SIZE) {
401 dbug(1,dprintf("bad len"));
405 controller = (byte)((msg->header.controller &0x7f)-1);
407 /* controller starts with 0 up to (max_adapter - 1) */
408 if ( controller >= max_adapter )
410 dbug(1,dprintf("invalid ctrl"));
414 a = &adapter[controller];
416 if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
418 dbug(1,dprintf("plci=%x",msg->header.plci));
419 plci = &a->plci[msg->header.plci-1];
420 ncci = GET_WORD(&msg->header.ncci);
423 || (plci->State == INC_CON_PENDING)
424 || (plci->State == INC_CON_ALERT)
425 || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
427 || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428 || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
430 i = plci->msg_in_read_pos;
431 j = plci->msg_in_write_pos;
434 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435 i += MSG_IN_QUEUE_SIZE - j;
442 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
444 if (i > MSG_IN_QUEUE_SIZE - n)
445 i = MSG_IN_QUEUE_SIZE - n + 1;
449 if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
452 dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453 msg->header.length, plci->msg_in_write_pos,
454 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
459 if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460 || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
462 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
465 if (msg->header.command == _DATA_B3_R)
467 if (msg->header.length < 20)
469 dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
472 ncci_ptr = &(a->ncci[ncci]);
473 n = ncci_ptr->data_pending;
474 l = ncci_ptr->data_ack_pending;
475 k = plci->msg_in_read_pos;
476 while (k != plci->msg_in_write_pos)
478 if (k == plci->msg_in_wrap_pos)
480 if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481 && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
484 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
488 k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489 MSG_IN_OVERHEAD + 3) & 0xfffc;
492 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
494 dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495 ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
499 if (plci->req_in || plci->internal_command)
501 if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502 && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
504 dbug(0,dprintf("Q-FULL3(requeue)"));
513 if (plci->req_in || plci->internal_command)
517 plci->command = msg->header.command;
518 plci->number = msg->header.number;
523 dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524 msg->header.command, plci->req_in, plci->internal_command,
525 msg->header.length, plci->msg_in_write_pos,
526 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
528 plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530 for (i = 0; i < msg->header.length; i++)
531 ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532 if (m->header.command == _DATA_B3_R)
535 m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
539 j = (j + 3) & 0xfffc;
541 *((APPL * *)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
551 dbug(1,dprintf("com=%x",msg->header.command));
553 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554 for(i=0, ret = _BAD_MSG;
555 i<(sizeof(ftable)/sizeof(struct _ftable));
558 if(ftable[i].command==msg->header.command) {
559 /* break loop if the message is correct, otherwise continue scan */
560 /* (for example: CONNECT_B3_T90_ACT_RES has two specifications) */
561 if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
565 for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
569 dbug(1,dprintf("BAD_MSG"));
570 if(plci) plci->command = 0;
575 c = ftable[i].function(GET_DWORD(&msg->header.controller),
582 channel_xmit_extended_xon (plci);
584 if(c==1) send_req(plci);
585 if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
586 if(plci && !plci->req_in) plci->command = 0;
591 /*------------------------------------------------------------------*/
592 /* api_parse function, check the format of api messages */
593 /*------------------------------------------------------------------*/
595 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
600 for(i=0,p=0; format[i]; i++) {
603 parms[i].info = &msg[p];
618 parms[i].length = msg[p+1] + (msg[p+2]<<8);
619 p +=(parms[i].length +3);
622 parms[i].length = msg[p];
623 p +=(parms[i].length +1);
628 if(p>length) return true;
630 if(parms) parms[i].info = NULL;
634 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
640 for (i = 0; format[i] != '\0'; i++)
642 out->parms[i].info = p;
643 out->parms[i].length = in[i].length;
656 n = in[i].length + 1;
659 for (j = 0; j < n; j++)
660 *(p++) = in[i].info[j];
662 out->parms[i].info = NULL;
663 out->parms[i].length = 0;
666 static void api_load_msg(API_SAVE *in, API_PARSE *out)
673 out[i].info = in->parms[i].info;
674 out[i].length = in->parms[i].length;
675 } while (in->parms[i++].info);
679 /*------------------------------------------------------------------*/
680 /* CAPI remove function */
681 /*------------------------------------------------------------------*/
683 word api_remove_start(void)
688 if(!remove_started) {
689 remove_started = true;
690 for(i=0;i<max_adapter;i++) {
691 if(adapter[i].request) {
692 for(j=0;j<adapter[i].max_plci;j++) {
693 if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
700 for(i=0;i<max_adapter;i++) {
701 if(adapter[i].request) {
702 for(j=0;j<adapter[i].max_plci;j++) {
703 if(adapter[i].plci[j].Sig.Id) return 1;
708 api_remove_complete();
713 /*------------------------------------------------------------------*/
714 /* internal command queue */
715 /*------------------------------------------------------------------*/
717 static void init_internal_command_queue (PLCI *plci)
721 dbug (1, dprintf ("%s,%d: init_internal_command_queue",
722 (char *)(FILE_), __LINE__));
724 plci->internal_command = 0;
725 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
726 plci->internal_command_queue[i] = NULL;
730 static void start_internal_command (dword Id, PLCI *plci, t_std_internal_command command_function)
734 dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
735 UnMapId (Id), (char *)(FILE_), __LINE__));
737 if (plci->internal_command == 0)
739 plci->internal_command_queue[0] = command_function;
740 (* command_function)(Id, plci, OK);
745 while (plci->internal_command_queue[i] != NULL)
747 plci->internal_command_queue[i] = command_function;
752 static void next_internal_command (dword Id, PLCI *plci)
756 dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
757 UnMapId (Id), (char *)(FILE_), __LINE__));
759 plci->internal_command = 0;
760 plci->internal_command_queue[0] = NULL;
761 while (plci->internal_command_queue[1] != NULL)
763 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
764 plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
765 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
766 (*(plci->internal_command_queue[0]))(Id, plci, OK);
767 if (plci->internal_command != 0)
769 plci->internal_command_queue[0] = NULL;
774 /*------------------------------------------------------------------*/
775 /* NCCI allocate/remove function */
776 /*------------------------------------------------------------------*/
778 static dword ncci_mapping_bug = 0;
780 static word get_ncci (PLCI *plci, byte ch, word force_ncci)
782 DIVA_CAPI_ADAPTER *a;
786 if (!ch || a->ch_ncci[ch])
789 dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
790 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
799 if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
804 while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
806 if (ncci == MAX_NCCI+1)
813 while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
821 } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
823 } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
824 if (i < MAX_NL_CHANNEL+1)
826 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
827 ncci_mapping_bug, ch, force_ncci, i, k, j));
831 dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
832 ncci_mapping_bug, ch, force_ncci));
837 a->ncci_plci[ncci] = plci->Id;
838 a->ncci_state[ncci] = IDLE;
839 if (!plci->ncci_ring_list)
840 plci->ncci_ring_list = ncci;
842 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
843 a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
845 a->ncci_ch[ncci] = ch;
846 a->ch_ncci[ch] = (byte) ncci;
847 dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
848 ncci_mapping_bug, ch, force_ncci, ch, ncci));
854 static void ncci_free_receive_buffers (PLCI *plci, word ncci)
856 DIVA_CAPI_ADAPTER *a;
862 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
865 if (a->ncci_plci[ncci] == plci->Id)
870 dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
871 ncci_mapping_bug, Id));
876 ncci_code = ncci | (((word) a->Id) << 8);
877 for (i = 0; i < appl->MaxBuffer; i++)
879 if ((appl->DataNCCI[i] == ncci_code)
880 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
882 appl->DataNCCI[i] = 0;
890 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
892 if (a->ncci_plci[ncci] == plci->Id)
897 dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
898 ncci_mapping_bug, Id));
903 ncci_code = ncci | (((word) a->Id) << 8);
904 for (i = 0; i < appl->MaxBuffer; i++)
906 if ((appl->DataNCCI[i] == ncci_code)
907 && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
909 appl->DataNCCI[i] = 0;
919 static void cleanup_ncci_data (PLCI *plci, word ncci)
923 if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
925 ncci_ptr = &(plci->adapter->ncci[ncci]);
928 while (ncci_ptr->data_pending != 0)
930 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
931 TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
932 (ncci_ptr->data_out)++;
933 if (ncci_ptr->data_out == MAX_DATA_B3)
934 ncci_ptr->data_out = 0;
935 (ncci_ptr->data_pending)--;
938 ncci_ptr->data_out = 0;
939 ncci_ptr->data_pending = 0;
940 ncci_ptr->data_ack_out = 0;
941 ncci_ptr->data_ack_pending = 0;
946 static void ncci_remove (PLCI *plci, word ncci, byte preserve_ncci)
948 DIVA_CAPI_ADAPTER *a;
953 Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
955 ncci_free_receive_buffers (plci, ncci);
958 if (a->ncci_plci[ncci] != plci->Id)
961 dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
962 ncci_mapping_bug, Id, preserve_ncci));
966 cleanup_ncci_data (plci, ncci);
967 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
968 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
969 a->ch_ncci[a->ncci_ch[ncci]] = 0;
972 a->ncci_ch[ncci] = 0;
973 a->ncci_plci[ncci] = 0;
974 a->ncci_state[ncci] = IDLE;
975 i = plci->ncci_ring_list;
976 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
978 if ((i != 0) && (a->ncci_next[i] == ncci))
981 plci->ncci_ring_list = 0;
982 else if (plci->ncci_ring_list == ncci)
983 plci->ncci_ring_list = i;
984 a->ncci_next[i] = a->ncci_next[ncci];
986 a->ncci_next[ncci] = 0;
992 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
994 if (a->ncci_plci[ncci] == plci->Id)
996 cleanup_ncci_data (plci, ncci);
997 dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
998 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
999 a->ch_ncci[a->ncci_ch[ncci]] = 0;
1002 a->ncci_ch[ncci] = 0;
1003 a->ncci_plci[ncci] = 0;
1004 a->ncci_state[ncci] = IDLE;
1005 a->ncci_next[ncci] = 0;
1010 plci->ncci_ring_list = 0;
1015 /*------------------------------------------------------------------*/
1016 /* PLCI remove function */
1017 /*------------------------------------------------------------------*/
1019 static void plci_free_msg_in_queue (PLCI *plci)
1025 i = plci->msg_in_read_pos;
1026 while (i != plci->msg_in_write_pos)
1028 if (i == plci->msg_in_wrap_pos)
1030 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1033 TransmitBufferFree (plci->appl,
1034 (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1038 i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1039 MSG_IN_OVERHEAD + 3) & 0xfffc;
1043 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1049 static void plci_remove(PLCI * plci)
1053 dbug(1,dprintf("plci_remove(no plci)"));
1056 init_internal_command_queue (plci);
1057 dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058 if(plci_remove_check(plci))
1062 if (plci->Sig.Id == 0xff)
1064 dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065 if (plci->NL.Id && !plci->nl_remove_id)
1067 nl_req_ncci(plci,REMOVE,0);
1073 if (!plci->sig_remove_id
1075 || (plci->req_in!=plci->req_out)
1076 || (plci->nl_req || plci->sig_req)))
1078 sig_req(plci,HANGUP,0);
1082 ncci_remove (plci, 0, false);
1083 plci_free_msg_in_queue (plci);
1087 if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088 plci->State = OUTG_DIS_PENDING;
1091 /*------------------------------------------------------------------*/
1092 /* Application Group function helpers */
1093 /*------------------------------------------------------------------*/
1095 static void set_group_ind_mask (PLCI *plci)
1099 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100 plci->group_optimization_mask_table[i] = 0xffffffffL;
1103 static void clear_group_ind_mask_bit (PLCI *plci, word b)
1105 plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1108 static byte test_group_ind_mask_bit (PLCI *plci, word b)
1110 return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1113 /*------------------------------------------------------------------*/
1114 /* c_ind_mask operations for arbitrary MAX_APPL */
1115 /*------------------------------------------------------------------*/
1117 static void clear_c_ind_mask (PLCI *plci)
1121 for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122 plci->c_ind_mask_table[i] = 0;
1125 static byte c_ind_mask_empty (PLCI *plci)
1130 while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1132 return (i == C_IND_MASK_DWORDS);
1135 static void set_c_ind_mask_bit (PLCI *plci, word b)
1137 plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1140 static void clear_c_ind_mask_bit (PLCI *plci, word b)
1142 plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1145 static byte test_c_ind_mask_bit (PLCI *plci, word b)
1147 return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1150 static void dump_c_ind_mask (PLCI *plci)
1152 static char hex_digit_table[0x10] =
1153 {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1159 for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1163 for (j = 0; j < 4; j++)
1165 if (i+j < C_IND_MASK_DWORDS)
1167 d = plci->c_ind_mask_table[i+j];
1168 for (k = 0; k < 8; k++)
1170 *(--p) = hex_digit_table[d & 0xf];
1176 for (k = 0; k < 8; k++)
1181 dbug(1,dprintf ("c_ind_mask =%s", (char *) p));
1189 #define dump_plcis(a)
1193 /*------------------------------------------------------------------*/
1194 /* translation function for each message */
1195 /*------------------------------------------------------------------*/
1197 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1198 PLCI *plci, APPL *appl, API_PARSE *parms)
1207 API_PARSE ai_parms[5];
1211 static byte esc_chi[35] = {0x02,0x18,0x01};
1212 static byte lli[2] = {0x01,0x00};
1217 for(i=0;i<5;i++) ai_parms[i].length = 0;
1219 dbug(1,dprintf("connect_req(%d)",parms->length));
1220 Info = _WRONG_IDENTIFIER;
1223 if(a->adapter_disabled)
1225 dbug(1,dprintf("adapter disabled"));
1226 Id = ((word)1<<8)|a->Id;
1227 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1228 sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1231 Info = _OUT_OF_PLCI;
1235 plci = &a->plci[i-1];
1237 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1238 /* check 'external controller' bit for codec support */
1239 if(Id & EXT_CONTROLLER)
1241 if(AdvCodecSupport(a, plci, appl, 0) )
1244 sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1251 if(bp->length)LinkLayer = bp->info[3];
1256 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1259 if(ai_parms[0].length)
1261 ch = GET_WORD(ai_parms[0].info+1);
1262 if(ch>4) ch=0; /* safety -> ignore ChannelID */
1263 if(ch==4) /* explizit CHI in message */
1265 /* check length of B-CH struct */
1266 if((ai_parms[0].info)[3]>=1)
1268 if((ai_parms[0].info)[4]==CHI)
1270 p_chi = &((ai_parms[0].info)[5]);
1274 p_chi = &((ai_parms[0].info)[3]);
1276 if(p_chi[0]>35) /* check length of channel ID */
1278 Info = _WRONG_MESSAGE_FORMAT;
1281 else Info = _WRONG_MESSAGE_FORMAT;
1284 if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1286 dir = GET_WORD(ai_parms[0].info+3);
1289 for(i=0; i+5<=ai_parms[0].length; i++)
1291 if(ai_parms[0].info[i+5]!=0)
1293 if((ai_parms[0].info[i+5] | m) != 0xff)
1294 Info = _WRONG_MESSAGE_FORMAT;
1305 Info = _WRONG_MESSAGE_FORMAT;
1308 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1310 esc_chi[0] = (byte)(ai_parms[0].length - 2);
1311 for(i=0; i+5<=ai_parms[0].length; i++)
1312 esc_chi[i+3] = ai_parms[0].info[i+5];
1316 esc_chi[2] = (byte)channel;
1317 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1318 add_p(plci,LLI,lli);
1319 add_p(plci,ESC,esc_chi);
1320 plci->State = LOCAL_CONNECT;
1321 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL; /* dir 0=DTE, 1=DCE */
1326 else Info = _WRONG_MESSAGE_FORMAT;
1329 dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1330 plci->command = _CONNECT_R;
1331 plci->number = Number;
1332 /* x.31 or D-ch free SAPI in LinkLayer? */
1333 if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1334 if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1336 /* B-channel used for B3 connections (ch==0), or no B channel */
1337 /* is used (ch==2) or perm. connection (3) is used do a CALL */
1338 if(noCh) Info = add_b1(plci,&parms[5],2,0); /* no resource */
1339 else Info = add_b1(plci,&parms[5],ch,0);
1340 add_s(plci,OAD,&parms[2]);
1341 add_s(plci,OSA,&parms[4]);
1342 add_s(plci,BC,&parms[6]);
1343 add_s(plci,LLC,&parms[7]);
1344 add_s(plci,HLC,&parms[8]);
1345 CIP = GET_WORD(parms[0].info);
1346 if (a->Info_Mask[appl->Id-1] & 0x200)
1348 /* early B3 connect (CIP mask bit 9) no release after a disc */
1349 add_p(plci,LLI,"\x01\x01");
1351 if(GET_WORD(parms[0].info)<29) {
1352 add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1353 add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1355 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1356 sig_req(plci,ASSIGN,DSIG_ID);
1360 /* D-Channel used for B3 connections */
1361 plci->Sig.Id = 0xff;
1365 if(!Info && ch!=2 && !noCh ) {
1366 Info = add_b23(plci,&parms[5]);
1368 if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1374 if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1376 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1378 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1379 plci->spoofed_msg = CALL_REQ;
1380 plci->internal_command = BLOCK_PLCI;
1382 dbug(1,dprintf("Spoof"));
1386 if(ch==4)add_p(plci,CHI,p_chi);
1387 add_s(plci,CPN,&parms[1]);
1388 add_s(plci,DSA,&parms[3]);
1389 if(noCh) add_p(plci,ESC,"\x02\x18\xfd"); /* D-channel, no B-L3 */
1390 add_ai(plci,&parms[9]);
1391 if(!dir)sig_req(plci,CALL_REQ,0);
1394 plci->command = PERM_LIST_REQ;
1396 sig_req(plci,LISTEN_REQ,0);
1415 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1416 PLCI *plci, APPL *appl, API_PARSE *parms)
1420 static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1421 static byte esc_t[] = {0x03,0x08,0x00,0x00};
1423 API_PARSE ai_parms[5];
1427 dbug(1,dprintf("connect_res(no plci)"));
1428 return 0; /* no plci, no send */
1431 dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1432 for(i=0;i<5;i++) ai_parms[i].length = 0;
1434 dbug(1,dprintf("ai->length=%d",ai->length));
1438 if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1440 dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1442 if(ai_parms[0].length)
1444 ch = GET_WORD(ai_parms[0].info+1);
1445 dbug(1,dprintf("BCH-I=0x%x",ch));
1450 if(plci->State==INC_CON_CONNECTED_ALERT)
1452 dbug(1,dprintf("Connected Alert Call_Res"));
1453 if (a->Info_Mask[appl->Id-1] & 0x200)
1455 /* early B3 connect (CIP mask bit 9) no release after a disc */
1456 add_p(plci,LLI,"\x01\x01");
1458 add_s(plci, CONN_NR, &parms[2]);
1459 add_s(plci, LLC, &parms[4]);
1460 add_ai(plci, &parms[5]);
1461 plci->State = INC_CON_ACCEPT;
1462 sig_req(plci, CALL_RES,0);
1465 else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1466 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1467 dump_c_ind_mask (plci);
1468 Reject = GET_WORD(parms[0].info);
1469 dbug(1,dprintf("Reject=0x%x",Reject));
1472 if(c_ind_mask_empty (plci))
1474 if((Reject&0xff00)==0x3400)
1476 esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1477 add_p(plci,ESC,esc_t);
1478 add_ai(plci, &parms[5]);
1479 sig_req(plci,REJECT,0);
1481 else if(Reject==1 || Reject>9)
1483 add_ai(plci, &parms[5]);
1484 sig_req(plci,HANGUP,0);
1488 esc_t[2] = cau_t[(Reject&0x000f)];
1489 add_p(plci,ESC,esc_t);
1490 add_ai(plci, &parms[5]);
1491 sig_req(plci,REJECT,0);
1497 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1502 if(Id & EXT_CONTROLLER){
1503 if(AdvCodecSupport(a, plci, appl, 0)){
1504 dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1505 sig_req(plci,HANGUP,0);
1508 if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1510 Info = add_b23(plci, &parms[1]);
1513 dbug(1,dprintf("connect_res(error from add_b23)"));
1514 sig_req(plci,HANGUP,0);
1519 nl_req_ncci(plci, ASSIGN, 0);
1528 Info = add_b23(plci, &parms[1]);
1531 dbug(1,dprintf("connect_res(error from add_b23 2)"));
1532 sig_req(plci,HANGUP,0);
1536 nl_req_ncci(plci, ASSIGN, 0);
1539 if(plci->spoofed_msg==SPOOFING_REQUIRED)
1541 api_save_msg(parms, "wsssss", &plci->saved_msg);
1542 plci->spoofed_msg = CALL_RES;
1543 plci->internal_command = BLOCK_PLCI;
1545 dbug(1,dprintf("Spoof"));
1549 add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1550 if (a->Info_Mask[appl->Id-1] & 0x200)
1552 /* early B3 connect (CIP mask bit 9) no release after a disc */
1553 add_p(plci,LLI,"\x01\x01");
1555 add_s(plci, CONN_NR, &parms[2]);
1556 add_s(plci, LLC, &parms[4]);
1557 add_ai(plci, &parms[5]);
1558 plci->State = INC_CON_ACCEPT;
1559 sig_req(plci, CALL_RES,0);
1562 for(i=0; i<max_appl; i++) {
1563 if(test_c_ind_mask_bit (plci, i)) {
1564 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1572 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1573 PLCI *plci, APPL *appl, API_PARSE *msg)
1575 dbug(1,dprintf("connect_a_res"));
1579 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1580 PLCI *plci, APPL *appl, API_PARSE *msg)
1585 dbug(1,dprintf("disconnect_req"));
1587 Info = _WRONG_IDENTIFIER;
1591 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1593 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1595 for(i=0; i<max_appl; i++)
1597 if(test_c_ind_mask_bit (plci, i))
1598 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1600 plci->State = OUTG_DIS_PENDING;
1602 if(plci->Sig.Id && plci->appl)
1605 if(plci->Sig.Id!=0xff)
1607 if(plci->State!=INC_DIS_PENDING)
1609 add_ai(plci, &msg[0]);
1610 sig_req(plci,HANGUP,0);
1611 plci->State = OUTG_DIS_PENDING;
1617 if (plci->NL.Id && !plci->nl_remove_id)
1619 mixer_remove (plci);
1620 nl_req_ncci(plci,REMOVE,0);
1621 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1622 sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1623 plci->State = INC_DIS_PENDING;
1630 if(!appl) return false;
1631 sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1635 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1636 PLCI *plci, APPL *appl, API_PARSE *msg)
1638 dbug(1,dprintf("disconnect_res"));
1641 /* clear ind mask bit, just in case of collsion of */
1642 /* DISCONNECT_IND and CONNECT_RES */
1643 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1644 ncci_free_receive_buffers (plci, 0);
1645 if(plci_remove_check(plci))
1649 if(plci->State==INC_DIS_PENDING
1650 || plci->State==SUSPENDING) {
1651 if(c_ind_mask_empty (plci)) {
1652 if(plci->State!=SUSPENDING)plci->State = IDLE;
1653 dbug(1,dprintf("chs=%d",plci->channels));
1654 if(!plci->channels) {
1663 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1664 PLCI *plci, APPL *appl, API_PARSE *parms)
1669 dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1671 Info = _WRONG_IDENTIFIER;
1674 a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1675 a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1676 dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1677 if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1678 a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */
1681 /* check if external controller listen and switch listen on or off*/
1682 if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1683 if(a->profile.Global_Options & ON_BOARD_CODEC) {
1684 dummy_plci.State = IDLE;
1685 a->codec_listen[appl->Id-1] = &dummy_plci;
1686 a->TelOAD[0] = (byte)(parms[3].length);
1687 for(i=1;parms[3].length>=i && i<22;i++) {
1688 a->TelOAD[i] = parms[3].info[i];
1691 a->TelOSA[0] = (byte)(parms[4].length);
1692 for(i=1;parms[4].length>=i && i<22;i++) {
1693 a->TelOSA[i] = parms[4].info[i];
1697 else Info = 0x2002; /* wrong controller, codec not supported */
1699 else{ /* clear listen */
1700 a->codec_listen[appl->Id-1] = (PLCI *)0;
1709 if (a) listen_check(a);
1713 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1714 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 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1824 PLCI *plci, APPL *appl, API_PARSE *msg)
1826 dbug(1,dprintf("info_res"));
1830 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1831 PLCI *plci, APPL *appl, API_PARSE *msg)
1836 dbug(1,dprintf("alert_req"));
1838 Info = _WRONG_IDENTIFIER;
1841 Info = _ALERT_IGNORED;
1842 if(plci->State!=INC_CON_ALERT) {
1843 Info = _WRONG_STATE;
1844 if(plci->State==INC_CON_PENDING) {
1846 plci->State=INC_CON_ALERT;
1847 add_ai(plci, &msg[0]);
1848 sig_req(plci,CALL_ALERT,0);
1861 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1862 PLCI *plci, APPL *appl, API_PARSE *msg)
1869 long relatedPLCIvalue;
1870 DIVA_CAPI_ADAPTER * relatedadapter;
1871 byte * SSparms = "";
1872 byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
1873 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1875 API_PARSE ss_parms[11];
1881 dbug(1,dprintf("facility_req"));
1882 for(i=0;i<9;i++) ss_parms[i].length = 0;
1888 dbug(1,dprintf("wrong Ctrl"));
1889 Info = _WRONG_IDENTIFIER;
1892 selector = GET_WORD(msg[0].info);
1898 case SELECTOR_HANDSET:
1899 Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1902 case SELECTOR_SU_SERV:
1905 Info = _WRONG_MESSAGE_FORMAT;
1908 SSreq = GET_WORD(&(msg[1].info[1]));
1909 PUT_WORD(&RCparms[1],SSreq);
1913 case S_GET_SUPPORTED_SERVICES:
1916 rplci = &a->plci[i-1];
1918 add_p(rplci,CAI,"\x01\x80");
1919 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1920 sig_req(rplci,ASSIGN,DSIG_ID);
1925 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1926 SSparms = (byte *)SSstruct;
1929 rplci->internal_command = GETSERV_REQ_PEND;
1930 rplci->number = Number;
1932 sig_req(rplci,S_SUPPORTED,0);
1938 if(parms->length==7)
1940 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1942 dbug(1,dprintf("format wrong"));
1943 Info = _WRONG_MESSAGE_FORMAT;
1949 Info = _WRONG_MESSAGE_FORMAT;
1952 a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1953 if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1957 rplci = &a->plci[i-1];
1959 add_p(rplci,CAI,"\x01\x80");
1960 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1961 sig_req(rplci,ASSIGN,DSIG_ID);
1968 rplci->internal_command = GET_MWI_STATE;
1969 rplci->number = Number;
1970 sig_req(rplci,MWI_POLL,0);
1976 api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1977 if(plci && plci->State && plci->SuppState==IDLE)
1979 plci->SuppState = HOLD_REQUEST;
1980 plci->command = C_HOLD_REQ;
1981 add_s(plci,CAI,&ss_parms[1]);
1982 sig_req(plci,CALL_HOLD,0);
1986 else Info = 0x3010; /* wrong state */
1989 if(plci && plci->State && plci->SuppState==CALL_HELD)
1991 if(Id & EXT_CONTROLLER)
1993 if(AdvCodecSupport(a, plci, appl, 0))
1995 Info = 0x3010; /* wrong state */
2001 plci->SuppState = RETRIEVE_REQUEST;
2002 plci->command = C_RETRIEVE_REQ;
2003 if(plci->spoofed_msg==SPOOFING_REQUIRED)
2005 plci->spoofed_msg = CALL_RETRIEVE;
2006 plci->internal_command = BLOCK_PLCI;
2008 dbug(1,dprintf("Spoof"));
2013 sig_req(plci,CALL_RETRIEVE,0);
2018 else Info = 0x3010; /* wrong state */
2023 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2025 dbug(1,dprintf("format wrong"));
2026 Info = _WRONG_MESSAGE_FORMAT;
2030 if(plci && plci->State)
2032 add_s(plci,CAI,&ss_parms[2]);
2033 plci->command = SUSPEND_REQ;
2034 sig_req(plci,SUSPEND,0);
2035 plci->State = SUSPENDING;
2038 else Info = 0x3010; /* wrong state */
2042 if(!(i=get_plci(a)) )
2044 Info = _OUT_OF_PLCI;
2047 rplci = &a->plci[i-1];
2049 rplci->number = Number;
2051 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2052 /* check 'external controller' bit for codec support */
2053 if(Id & EXT_CONTROLLER)
2055 if(AdvCodecSupport(a, rplci, appl, 0) )
2064 if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2066 dbug(1,dprintf("format wrong"));
2068 Info = _WRONG_MESSAGE_FORMAT;
2073 dummy.info = "\x00";
2074 add_b1(rplci, &dummy, 0, 0);
2075 if (a->Info_Mask[appl->Id-1] & 0x200)
2077 /* early B3 connect (CIP mask bit 9) no release after a disc */
2078 add_p(rplci,LLI,"\x01\x01");
2080 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2081 sig_req(rplci,ASSIGN,DSIG_ID);
2083 add_s(rplci,CAI,&ss_parms[2]);
2084 rplci->command = RESUME_REQ;
2085 sig_req(rplci,RESUME,0);
2086 rplci->State = RESUMING;
2090 case S_CONF_BEGIN: /* Request */
2092 case S_CONF_ISOLATE:
2093 case S_CONF_REATTACH:
2094 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2096 dbug(1,dprintf("format wrong"));
2097 Info = _WRONG_MESSAGE_FORMAT;
2100 if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2102 d = GET_DWORD(ss_parms[2].info);
2105 dbug(1,dprintf("format wrong"));
2106 Info = _WRONG_MESSAGE_FORMAT;
2109 plci->ptyState = (byte)SSreq;
2115 cai[1] = CONF_BEGIN;
2116 plci->internal_command = CONF_BEGIN_REQ_PEND;
2120 plci->internal_command = CONF_DROP_REQ_PEND;
2122 case S_CONF_ISOLATE:
2123 cai[1] = CONF_ISOLATE;
2124 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2126 case S_CONF_REATTACH:
2127 cai[1] = CONF_REATTACH;
2128 plci->internal_command = CONF_REATTACH_REQ_PEND;
2131 cai[2] = (byte)d; /* Conference Size resp. PartyId */
2132 add_p(plci,CAI,cai);
2133 sig_req(plci,S_SERVICE,0);
2137 else Info = 0x3010; /* wrong state */
2144 if(parms->length==7)
2146 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2148 dbug(1,dprintf("format wrong"));
2149 Info = _WRONG_MESSAGE_FORMAT;
2153 else if(parms->length==8) /* workaround for the T-View-S */
2155 if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2157 dbug(1,dprintf("format wrong"));
2158 Info = _WRONG_MESSAGE_FORMAT;
2164 Info = _WRONG_MESSAGE_FORMAT;
2169 Info = _WRONG_MESSAGE_FORMAT;
2174 Info = _WRONG_IDENTIFIER;
2177 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2178 relatedPLCIvalue &= 0x0000FFFF;
2179 dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2180 /* controller starts with 0 up to (max_adapter - 1) */
2181 if (((relatedPLCIvalue & 0x7f) == 0)
2182 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2183 || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2185 if(SSreq==S_3PTY_END)
2187 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2192 Info = 0x3010; /* wrong state */
2198 relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2199 relatedPLCIvalue >>=8;
2201 for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2203 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2205 rplci = &relatedadapter->plci[i];
2208 if(!rplci || !relatedPLCIvalue)
2210 if(SSreq==S_3PTY_END)
2212 dbug(1, dprintf("use 2nd PLCI=PLCI"));
2217 Info = 0x3010; /* wrong state */
2223 dbug(1,dprintf("rplci:%x",rplci));
2224 dbug(1,dprintf("plci:%x",plci));
2225 dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2226 dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2227 dbug(1,dprintf("SSreq:%x",SSreq));
2228 dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2229 dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2230 dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2232 /* send PTY/ECT req, cannot check all states because of US stuff */
2233 if( !rplci->internal_command && rplci->appl )
2236 rplci->relatedPTYPLCI = plci;
2237 plci->relatedPTYPLCI = rplci;
2238 rplci->ptyState = (byte)SSreq;
2241 rplci->internal_command = ECT_REQ_PEND;
2242 cai[1] = ECT_EXECUTE;
2244 rplci->vswitchstate=0;
2246 rplci->vsprotdialect=0;
2247 plci->vswitchstate=0;
2249 plci->vsprotdialect=0;
2252 else if(SSreq==S_CONF_ADD)
2254 rplci->internal_command = CONF_ADD_REQ_PEND;
2259 rplci->internal_command = PTY_REQ_PEND;
2260 cai[1] = (byte)(SSreq-3);
2262 rplci->number = Number;
2263 if(plci!=rplci) /* explicit invocation */
2266 cai[2] = plci->Sig.Id;
2267 dbug(1,dprintf("explicit invocation"));
2271 dbug(1,dprintf("implicit invocation"));
2274 add_p(rplci,CAI,cai);
2275 sig_req(rplci,S_SERVICE,0);
2281 dbug(0,dprintf("Wrong line"));
2282 Info = 0x3010; /* wrong state */
2287 case S_CALL_DEFLECTION:
2288 if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2290 dbug(1,dprintf("format wrong"));
2291 Info = _WRONG_MESSAGE_FORMAT;
2296 Info = _WRONG_IDENTIFIER;
2299 /* reuse unused screening indicator */
2300 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2302 plci->internal_command = CD_REQ_PEND;
2303 appl->CDEnable = true;
2305 cai[1] = CALL_DEFLECTION;
2306 add_p(plci,CAI,cai);
2307 add_p(plci,CPN,ss_parms[3].info);
2308 sig_req(plci,S_SERVICE,0);
2313 case S_CALL_FORWARDING_START:
2314 if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2316 dbug(1,dprintf("format wrong"));
2317 Info = _WRONG_MESSAGE_FORMAT;
2323 rplci = &a->plci[i-1];
2325 add_p(rplci,CAI,"\x01\x80");
2326 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2327 sig_req(rplci,ASSIGN,DSIG_ID);
2332 Info = _OUT_OF_PLCI;
2336 /* reuse unused screening indicator */
2337 rplci->internal_command = CF_START_PEND;
2339 rplci->number = Number;
2340 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2342 cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2343 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2344 add_p(rplci,CAI,cai);
2345 add_p(rplci,OAD,ss_parms[5].info);
2346 add_p(rplci,CPN,ss_parms[6].info);
2347 sig_req(rplci,S_SERVICE,0);
2352 case S_INTERROGATE_DIVERSION:
2353 case S_INTERROGATE_NUMBERS:
2354 case S_CALL_FORWARDING_STOP:
2355 case S_CCBS_REQUEST:
2356 case S_CCBS_DEACTIVATE:
2357 case S_CCBS_INTERROGATE:
2360 case S_INTERROGATE_NUMBERS:
2361 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2363 dbug(0,dprintf("format wrong"));
2364 Info = _WRONG_MESSAGE_FORMAT;
2367 case S_CCBS_REQUEST:
2368 case S_CCBS_DEACTIVATE:
2369 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2371 dbug(0,dprintf("format wrong"));
2372 Info = _WRONG_MESSAGE_FORMAT;
2375 case S_CCBS_INTERROGATE:
2376 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2378 dbug(0,dprintf("format wrong"));
2379 Info = _WRONG_MESSAGE_FORMAT;
2383 if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2385 dbug(0,dprintf("format wrong"));
2386 Info = _WRONG_MESSAGE_FORMAT;
2395 rplci = &a->plci[i-1];
2398 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2399 cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2402 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2403 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2404 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2406 case S_CALL_FORWARDING_STOP:
2407 rplci->internal_command = CF_STOP_PEND;
2408 cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2410 case S_CCBS_REQUEST:
2411 cai[1] = CCBS_REQUEST;
2412 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2414 case S_CCBS_DEACTIVATE:
2415 cai[1] = CCBS_DEACTIVATE;
2416 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2418 case S_CCBS_INTERROGATE:
2419 cai[1] = CCBS_INTERROGATE;
2420 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2427 rplci->number = Number;
2428 add_p(rplci,CAI,"\x01\x80");
2429 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2430 sig_req(rplci,ASSIGN,DSIG_ID);
2435 Info = _OUT_OF_PLCI;
2439 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2442 case S_INTERROGATE_NUMBERS:
2444 add_p(rplci,CAI,cai);
2446 case S_CCBS_REQUEST:
2447 case S_CCBS_DEACTIVATE:
2449 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2450 add_p(rplci,CAI,cai);
2452 case S_CCBS_INTERROGATE:
2454 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2455 add_p(rplci,CAI,cai);
2456 add_p(rplci,OAD,ss_parms[4].info);
2460 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2461 add_p(rplci,CAI,cai);
2462 add_p(rplci,OAD,ss_parms[5].info);
2466 sig_req(rplci,S_SERVICE,0);
2471 case S_MWI_ACTIVATE:
2472 if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2474 dbug(1,dprintf("format wrong"));
2475 Info = _WRONG_MESSAGE_FORMAT;
2482 rplci = &a->plci[i-1];
2484 rplci->cr_enquiry=true;
2485 add_p(rplci,CAI,"\x01\x80");
2486 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2487 sig_req(rplci,ASSIGN,DSIG_ID);
2492 Info = _OUT_OF_PLCI;
2499 rplci->cr_enquiry=false;
2503 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2505 rplci->number = Number;
2508 cai[1] = ACTIVATION_MWI; /* Function */
2509 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2510 PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2511 PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2512 PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2513 PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2514 add_p(rplci,CAI,cai);
2515 add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2516 add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2517 add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2518 add_p(rplci,UID,ss_parms[10].info); /* Time */
2519 sig_req(rplci,S_SERVICE,0);
2523 case S_MWI_DEACTIVATE:
2524 if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2526 dbug(1,dprintf("format wrong"));
2527 Info = _WRONG_MESSAGE_FORMAT;
2534 rplci = &a->plci[i-1];
2536 rplci->cr_enquiry=true;
2537 add_p(rplci,CAI,"\x01\x80");
2538 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2539 sig_req(rplci,ASSIGN,DSIG_ID);
2544 Info = _OUT_OF_PLCI;
2551 rplci->cr_enquiry=false;
2555 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2557 rplci->number = Number;
2560 cai[1] = DEACTIVATION_MWI; /* Function */
2561 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2562 PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2563 add_p(rplci,CAI,cai);
2564 add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2565 add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2566 sig_req(rplci,S_SERVICE,0);
2571 Info = 0x300E; /* not supported */
2574 break; /* case SELECTOR_SU_SERV: end */
2578 return (dtmf_request (Id, Number, a, plci, appl, msg));
2582 case SELECTOR_LINE_INTERCONNECT:
2583 return (mixer_request (Id, Number, a, plci, appl, msg));
2587 case PRIV_SELECTOR_ECHO_CANCELLER:
2588 appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2589 return (ec_request (Id, Number, a, plci, appl, msg));
2591 case SELECTOR_ECHO_CANCELLER:
2592 appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2593 return (ec_request (Id, Number, a, plci, appl, msg));
2596 case SELECTOR_V42BIS:
2598 Info = _FACILITY_NOT_SUPPORTED;
2600 } /* end of switch(selector) */
2603 dbug(1,dprintf("SendFacRc"));
2605 _FACILITY_R|CONFIRM,
2608 "wws",Info,selector,SSparms);
2612 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2613 PLCI *plci, APPL *appl, API_PARSE *msg)
2615 dbug(1,dprintf("facility_res"));
2619 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2620 PLCI *plci, APPL *appl, API_PARSE *parms)
2626 word fax_control_bits, fax_feature_bits, fax_info_change;
2630 API_PARSE fax_parms[9];
2634 dbug(1,dprintf("connect_b3_req"));
2637 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2638 || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2640 Info = _WRONG_STATE;
2644 /* local reply if assign unsuccessfull
2645 or B3 protocol allows only one layer 3 connection
2646 and already connected
2647 or B2 protocol not any LAPD
2648 and connect_b3_req contradicts originate/answer direction */
2650 || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2651 && ((plci->channels != 0)
2652 || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2653 && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2655 dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2656 plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2657 Info = _WRONG_STATE;
2659 _CONNECT_B3_R|CONFIRM,
2665 plci->requested_options_conn = 0;
2669 if(plci->B3_prot==2 || plci->B3_prot==3)
2674 if(ncpi->info[2] || ncpi->info[3])
2676 pvc[0] = ncpi->info[3];
2677 pvc[1] = ncpi->info[2];
2683 if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2684 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2688 else if(plci->B3_prot==5)
2690 if (plci->NL.Id && !plci->nl_remove_id)
2692 fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2693 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2694 if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2695 || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2697 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2698 fax_info_change = false;
2699 if (ncpi->length >= 4)
2701 w = GET_WORD(&ncpi->info[3]);
2702 if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2704 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2705 (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2706 ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2707 fax_info_change = true;
2709 fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2710 if (w & 0x0002) /* Fax-polling request */
2711 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2712 if ((w & 0x0004) /* Request to send / poll another document */
2713 && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2715 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2717 if (ncpi->length >= 6)
2719 w = GET_WORD(&ncpi->info[5]);
2720 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2722 ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2723 fax_info_change = true;
2726 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2727 && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2729 plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2731 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2732 && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2734 plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2736 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2737 T30_CONTROL_BIT_ACCEPT_PASSWORD);
2738 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2739 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2741 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2742 Info = _WRONG_MESSAGE_FORMAT;
2745 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2746 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2748 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2749 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2750 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2752 w = fax_parms[4].length;
2755 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2756 for (i = 0; i < w; i++)
2757 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2758 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2759 len = (byte)(((T30_INFO *) 0)->station_id + 20);
2760 w = fax_parms[5].length;
2763 plci->fax_connect_info_buffer[len++] = (byte) w;
2764 for (i = 0; i < w; i++)
2765 plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2766 w = fax_parms[6].length;
2769 plci->fax_connect_info_buffer[len++] = (byte) w;
2770 for (i = 0; i < w; i++)
2771 plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2772 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2773 & (1L << PRIVATE_FAX_NONSTANDARD))
2775 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2777 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2778 plci->fax_connect_info_buffer[len++] = 0;
2782 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2783 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2784 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2785 for (i = 0; i < fax_parms[7].length; i++)
2786 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2793 len = (byte)(&(((T30_INFO *) 0)->universal_6));
2795 fax_info_change = true;
2798 if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2800 PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2801 fax_info_change = true;
2806 plci->fax_connect_info_length = len;
2807 if (fax_info_change)
2809 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2811 start_internal_command (Id, plci, fax_connect_info_command);
2816 start_internal_command (Id, plci, fax_adjust_b23_command);
2822 else Info = _WRONG_STATE;
2824 else Info = _WRONG_STATE;
2827 else if (plci->B3_prot == B3_RTP)
2829 plci->internal_req_buffer[0] = ncpi->length + 1;
2830 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2831 for (w = 0; w < ncpi->length; w++)
2832 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2833 start_internal_command (Id, plci, rtp_connect_b3_req_command);
2839 nl_req_ncci(plci,req,0);
2844 else Info = _WRONG_IDENTIFIER;
2847 _CONNECT_B3_R|CONFIRM,
2854 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2855 PLCI *plci, APPL *appl, API_PARSE *parms)
2864 API_PARSE fax_parms[9];
2869 dbug(1,dprintf("connect_b3_res"));
2871 ncci = (word)(Id>>16);
2873 if(a->ncci_state[ncci]==INC_CON_PENDING) {
2874 if (GET_WORD (&parms[0].info[0]) != 0)
2876 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2877 channel_request_xon (plci, a->ncci_ch[ncci]);
2878 channel_xmit_xon (plci);
2879 cleanup_ncci_data (plci, ncci);
2880 nl_req_ncci(plci,N_DISC,(byte)ncci);
2883 a->ncci_state[ncci] = INC_ACT_PENDING;
2885 req = N_CONNECT_ACK;
2887 if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2890 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2891 & (1L << PRIVATE_FAX_NONSTANDARD))
2893 if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2894 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2895 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2897 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2898 if (plci->fax_connect_info_length < len)
2900 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2901 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2903 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2905 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2909 if (plci->fax_connect_info_length <= len)
2910 plci->fax_connect_info_buffer[len] = 0;
2911 len += 1 + plci->fax_connect_info_buffer[len];
2912 if (plci->fax_connect_info_length <= len)
2913 plci->fax_connect_info_buffer[len] = 0;
2914 len += 1 + plci->fax_connect_info_buffer[len];
2915 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2916 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2917 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2918 for (i = 0; i < fax_parms[7].length; i++)
2919 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2921 plci->fax_connect_info_length = len;
2922 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2923 start_internal_command (Id, plci, fax_connect_ack_command);
2928 nl_req_ncci(plci,req,(byte)ncci);
2929 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2930 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2932 if (plci->B3_prot == 4)
2933 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2935 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2936 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2940 else if (plci->B3_prot == B3_RTP)
2942 plci->internal_req_buffer[0] = ncpi->length + 1;
2943 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2944 for (w = 0; w < ncpi->length; w++)
2945 plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2946 start_internal_command (Id, plci, rtp_connect_b3_res_command);
2952 if(ncpi->length>2) {
2953 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2954 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2956 nl_req_ncci(plci,req,(byte)ncci);
2957 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2958 if (plci->adjust_b_restore)
2960 plci->adjust_b_restore = false;
2961 start_internal_command (Id, plci, adjust_b_restore);
2970 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2971 PLCI *plci, APPL *appl, API_PARSE *parms)
2975 ncci = (word)(Id>>16);
2976 dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2978 if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2979 && (plci->State != OUTG_DIS_PENDING))
2981 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2982 a->ncci_state[ncci] = CONNECTED;
2983 if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2984 channel_request_xon (plci, a->ncci_ch[ncci]);
2985 channel_xmit_xon (plci);
2991 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2992 PLCI *plci, APPL *appl, API_PARSE *parms)
2998 dbug(1,dprintf("disconnect_b3_req"));
3000 Info = _WRONG_IDENTIFIER;
3001 ncci = (word)(Id>>16);
3004 Info = _WRONG_STATE;
3005 if ((a->ncci_state[ncci] == CONNECTED)
3006 || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3007 || (a->ncci_state[ncci] == INC_CON_PENDING)
3008 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3010 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3011 channel_request_xon (plci, a->ncci_ch[ncci]);
3012 channel_xmit_xon (plci);
3014 if (a->ncci[ncci].data_pending
3015 && ((plci->B3_prot == B3_TRANSPARENT)
3016 || (plci->B3_prot == B3_T30)
3017 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3019 plci->send_disc = (byte)ncci;
3025 cleanup_ncci_data (plci, ncci);
3027 if(plci->B3_prot==2 || plci->B3_prot==3)
3032 add_d(plci, (word)(ncpi->length - 3) ,(byte *)&(ncpi->info[4]));
3035 nl_req_ncci(plci,N_DISC,(byte)ncci);
3041 _DISCONNECT_B3_R|CONFIRM,
3048 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3049 PLCI *plci, APPL *appl, API_PARSE *parms)
3054 ncci = (word)(Id>>16);
3055 dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3057 plci->requested_options_conn = 0;
3058 plci->fax_connect_info_length = 0;
3059 plci->ncpi_state = 0x00;
3060 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3061 && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3063 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3065 for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3066 if(i<MAX_CHANNELS_PER_PLCI) {
3067 if(plci->channels)plci->channels--;
3068 for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3069 plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3071 ncci_free_receive_buffers (plci, ncci);
3073 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3074 if(plci->State == SUSPENDING){
3079 "ws", (word)3, "\x03\x04\x00\x00");
3080 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3088 if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3089 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3090 && (a->ncci_state[ncci] == INC_DIS_PENDING))
3092 ncci_free_receive_buffers (plci, ncci);
3094 nl_req_ncci(plci,N_EDATA,(byte)ncci);
3096 plci->adapter->ncci_state[ncci] = IDLE;
3097 start_internal_command (Id, plci, fax_disconnect_command);
3105 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3106 PLCI *plci, APPL *appl, API_PARSE *parms)
3114 dbug(1,dprintf("data_b3_req"));
3116 Info = _WRONG_IDENTIFIER;
3117 ncci = (word)(Id>>16);
3118 dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3122 Info = _WRONG_STATE;
3123 if ((a->ncci_state[ncci] == CONNECTED)
3124 || (a->ncci_state[ncci] == INC_ACT_PENDING))
3127 ncci_ptr = &(a->ncci[ncci]);
3128 i = ncci_ptr->data_out + ncci_ptr->data_pending;
3129 if (i >= MAX_DATA_B3)
3131 data = &(ncci_ptr->DBuffer[i]);
3132 data->Number = Number;
3133 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3134 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3137 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3141 data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3142 data->Length = GET_WORD(parms[1].info);
3143 data->Handle = GET_WORD(parms[2].info);
3144 data->Flags = GET_WORD(parms[3].info);
3145 (ncci_ptr->data_pending)++;
3147 /* check for delivery confirmation */
3148 if (data->Flags & 0x0004)
3150 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3151 if (i >= MAX_DATA_ACK)
3153 ncci_ptr->DataAck[i].Number = data->Number;
3154 ncci_ptr->DataAck[i].Handle = data->Handle;
3155 (ncci_ptr->data_ack_pending)++;
3166 if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3167 && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3170 TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3178 "ww",GET_WORD(parms[2].info),Info);
3183 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3184 PLCI *plci, APPL *appl, API_PARSE *parms)
3190 dbug(1,dprintf("data_b3_res"));
3192 ncci = (word)(Id>>16);
3194 n = GET_WORD(parms[0].info);
3195 dbug(1,dprintf("free(%d)",n));
3196 NCCIcode = ncci | (((word) a->Id) << 8);
3197 if(n<appl->MaxBuffer &&
3198 appl->DataNCCI[n]==NCCIcode &&
3199 (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3200 dbug(1,dprintf("found"));
3201 appl->DataNCCI[n] = 0;
3203 if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3204 channel_request_xon (plci, a->ncci_ch[ncci]);
3206 channel_xmit_xon (plci);
3208 if(appl->DataFlags[n] &4) {
3209 nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3217 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3218 PLCI *plci, APPL *appl, API_PARSE *parms)
3223 dbug(1,dprintf("reset_b3_req"));
3225 Info = _WRONG_IDENTIFIER;
3226 ncci = (word)(Id>>16);
3229 Info = _WRONG_STATE;
3230 switch (plci->B3_prot)
3234 if(a->ncci_state[ncci]==CONNECTED)
3236 nl_req_ncci(plci,N_RESET,(byte)ncci);
3241 case B3_TRANSPARENT:
3242 if(a->ncci_state[ncci]==CONNECTED)
3244 start_internal_command (Id, plci, reset_b3_command);
3250 /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3252 _RESET_B3_R|CONFIRM,
3259 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3260 PLCI *plci, APPL *appl, API_PARSE *parms)
3264 dbug(1,dprintf("reset_b3_res"));
3266 ncci = (word)(Id>>16);
3268 switch (plci->B3_prot)
3272 if(a->ncci_state[ncci]==INC_RES_PENDING)
3274 a->ncci_state[ncci] = CONNECTED;
3275 nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3284 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3285 PLCI *plci, APPL *appl, API_PARSE *parms)
3291 dbug(1,dprintf("connect_b3_t90_a_res"));
3293 ncci = (word)(Id>>16);
3295 if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3296 a->ncci_state[ncci] = CONNECTED;
3298 else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3299 a->ncci_state[ncci] = CONNECTED;
3301 req = N_CONNECT_ACK;
3303 /* parms[0]==0 for CAPI original message definition! */
3306 if(ncpi->length>2) {
3307 if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3308 add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3311 nl_req_ncci(plci,req,(byte)ncci);
3319 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3320 PLCI *plci, APPL *appl, API_PARSE *msg)
3325 API_PARSE bp_parms[7];
3329 Info = _WRONG_IDENTIFIER;
3333 dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3334 msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3335 dbug(1,dprintf("PlciState=0x%x",plci->State));
3336 for(i=0;i<7;i++) bp_parms[i].length = 0;
3338 /* check if no channel is open, no B3 connected only */
3339 if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3340 || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3342 Info = _WRONG_STATE;
3344 /* check message format and fill bp_parms pointer */
3345 else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3347 Info = _WRONG_MESSAGE_FORMAT;
3351 if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3352 { /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3353 if(Id & EXT_CONTROLLER)
3355 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3358 plci->State=INC_CON_CONNECTED_ALERT;
3360 clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3361 dump_c_ind_mask (plci);
3362 for(i=0; i<max_appl; i++) /* disconnect the other appls */
3363 { /* its quasi a connect */
3364 if(test_c_ind_mask_bit (plci, i))
3365 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3369 api_save_msg(msg, "s", &plci->saved_msg);
3371 if(Id & EXT_CONTROLLER)
3373 if(tel) /* external controller in use by this PLCI */
3375 if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3377 dbug(1,dprintf("Ext_Ctrl in use 1"));
3378 Info = _WRONG_STATE;
3381 else /* external controller NOT in use by this PLCI ? */
3383 if(a->AdvSignalPLCI)
3385 dbug(1,dprintf("Ext_Ctrl in use 2"));
3386 Info = _WRONG_STATE;
3388 else /* activate the codec */
3390 dbug(1,dprintf("Ext_Ctrl start"));
3391 if(AdvCodecSupport(a, plci, appl, 0) )
3393 dbug(1,dprintf("Error in codec procedures"));
3394 Info = _WRONG_STATE;
3396 else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3398 plci->spoofed_msg = AWAITING_SELECT_B;
3399 plci->internal_command = BLOCK_PLCI; /* lock other commands */
3401 dbug(1,dprintf("continue if codec loaded"));
3407 else /* external controller bit is OFF */
3409 if(tel) /* external controller in use, need to switch off */
3411 if(a->AdvSignalAppl==appl)
3413 CodecIdCheck(a, plci);
3416 dbug(1,dprintf("Ext_Ctrl disable"));
3420 dbug(1,dprintf("Ext_Ctrl not requested"));
3426 if (plci->call_dir & CALL_DIR_OUT)
3427 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3428 else if (plci->call_dir & CALL_DIR_IN)
3429 plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3430 start_internal_command (Id, plci, select_b_command);
3435 sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3439 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3440 PLCI *plci, APPL *appl, API_PARSE *parms)
3446 API_PARSE m_parms[5];
3451 static byte chi[2] = {0x01,0x00};
3452 static byte lli[2] = {0x01,0x00};
3453 static byte codec_cai[2] = {0x01,0x01};
3454 static byte null_msg = {0};
3455 static API_PARSE null_parms = { 0, &null_msg };
3459 dbug(1,dprintf("manufacturer_req"));
3460 for(i=0;i<5;i++) m_parms[i].length = 0;
3462 if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3463 Info = _WRONG_MESSAGE_FORMAT;
3465 command = GET_WORD(parms[1].info);
3470 case _DI_ASSIGN_PLCI:
3471 if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3472 Info = _WRONG_MESSAGE_FORMAT;
3475 codec = GET_WORD(m_parms[0].info);
3476 ch = m_parms[1].info[0];
3477 dir = m_parms[2].info[0];
3478 if((i=get_plci(a))) {
3479 plci = &a->plci[i-1];
3481 plci->command = _MANUFACTURER_R;
3482 plci->m_command = command;
3483 plci->number = Number;
3484 plci->State = LOCAL_CONNECT;
3485 Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3486 dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3488 if((ch==1 || ch==2) && (dir<=2)) {
3489 chi[1] = (byte)(0x80|ch);
3491 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3495 Info = add_b1(plci,&m_parms[3],0,0);
3498 add_p(plci,CAI,codec_cai);
3500 /* manual 'swich on' to the codec support without signalling */
3501 /* first 'assign plci' with this function, then use */
3503 if(AdvCodecSupport(a, plci, appl, 0) ) {
3504 Info = _RESOURCE_ERROR;
3507 Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3508 lli[1] = 0x10; /* local call codec stream */
3513 plci->State = LOCAL_CONNECT;
3514 plci->manufacturer = true;
3515 plci->command = _MANUFACTURER_R;
3516 plci->m_command = command;
3517 plci->number = Number;
3521 add_p(plci,LLI,lli);
3522 add_p(plci,CHI,chi);
3523 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3524 sig_req(plci,ASSIGN,DSIG_ID);
3528 Info = add_b23(plci,&m_parms[3]);
3531 nl_req_ncci(plci,ASSIGN,0);
3537 dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3538 if (plci->spoofed_msg==SPOOFING_REQUIRED)
3540 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3541 plci->spoofed_msg = AWAITING_MANUF_CON;
3542 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3548 sig_req(plci,CALL_REQ,0);
3551 sig_req(plci,LISTEN_REQ,0);
3558 _MANUFACTURER_R|CONFIRM,
3561 "dww",_DI_MANU_ID,command,Info);
3567 else Info = _OUT_OF_PLCI;
3573 Info = _WRONG_IDENTIFIER;
3576 if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3577 Info = _WRONG_MESSAGE_FORMAT;
3580 req = m_parms[0].info[0];
3581 plci->command = _MANUFACTURER_R;
3582 plci->m_command = command;
3583 plci->number = Number;
3586 plci->b_channel = getChannel(&m_parms[1]);
3587 mixer_set_bchannel_id_esc (plci, plci->b_channel);
3588 if(plci->spoofed_msg==SPOOFING_REQUIRED)
3590 plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3591 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3596 else if(req==LAW_REQ)
3598 plci->cr_enquiry = true;
3600 add_ss(plci,FTY,&m_parms[1]);
3601 sig_req(plci,req,0);
3605 if (plci->NL.Id && !plci->nl_remove_id)
3609 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3611 if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3613 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3614 cleanup_ncci_data (plci, ncci);
3615 nl_req_ncci(plci,N_DISC,(byte)ncci);
3619 mixer_remove (plci);
3620 nl_req_ncci(plci,REMOVE,0);
3627 /* signalling control for loop activation B-channel */
3630 Info = _WRONG_IDENTIFIER;
3634 plci->command = _MANUFACTURER_R;
3635 plci->number = Number;
3637 sig_req(plci,SIG_CTRL,0);
3640 else Info = _WRONG_MESSAGE_FORMAT;
3644 /* activation control for receiver/transmitter B-channel */
3647 Info = _WRONG_IDENTIFIER;
3651 plci->command = _MANUFACTURER_R;
3652 plci->number = Number;
3654 sig_req(plci,DSP_CTRL,0);
3657 else Info = _WRONG_MESSAGE_FORMAT;
3662 /* TEL_CTRL commands to support non standard adjustments: */
3663 /* Ring on/off, Handset micro volume, external micro vol. */
3664 /* handset+external speaker volume, receiver+transm. gain,*/
3665 /* handsfree on (hookinfo off), set mixer command */
3667 if(command == _DI_ADV_CODEC)
3669 if(!a->AdvCodecPLCI) {
3670 Info = _WRONG_STATE;
3673 v_plci = a->AdvCodecPLCI;
3679 && (m->info[1] == 0x1c)
3680 && (m->info[2] >= 1))
3682 if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3684 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3686 Info = _WRONG_STATE;
3689 a->adv_voice_coef_length = m->info[2] - 1;
3690 if (a->adv_voice_coef_length > m->length - 3)
3691 a->adv_voice_coef_length = (byte)(m->length - 3);
3692 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3693 a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3694 for (i = 0; i < a->adv_voice_coef_length; i++)
3695 a->adv_voice_coef_buffer[i] = m->info[4 + i];
3696 if (plci->B1_facilities & B1_FACILITY_VOICE)
3697 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3700 else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3702 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3704 Info = _FACILITY_NOT_SUPPORTED;
3708 plci->dtmf_parameter_length = m->info[2] - 1;
3709 if (plci->dtmf_parameter_length > m->length - 3)
3710 plci->dtmf_parameter_length = (byte)(m->length - 3);
3711 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3712 plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3713 for (i = 0; i < plci->dtmf_parameter_length; i++)
3714 plci->dtmf_parameter_buffer[i] = m->info[4+i];
3715 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3716 dtmf_parameter_write (plci);
3726 Info = _WRONG_IDENTIFIER;
3730 add_ss(v_plci,FTY,m);
3731 sig_req(v_plci,TEL_CTRL,0);
3734 else Info = _WRONG_MESSAGE_FORMAT;
3738 case _DI_OPTIONS_REQUEST:
3739 if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3740 Info = _WRONG_MESSAGE_FORMAT;
3743 if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3745 Info = _FACILITY_NOT_SUPPORTED;
3748 a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3754 Info = _WRONG_MESSAGE_FORMAT;
3760 _MANUFACTURER_R|CONFIRM,
3763 "dww",_DI_MANU_ID,command,Info);
3768 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3769 PLCI *plci, APPL *appl, API_PARSE *msg)
3773 API_PARSE m_parms[3];
3775 API_PARSE fax_parms[9];
3780 dbug(1,dprintf("manufacturer_res"));
3782 if ((msg[0].length == 0)
3783 || (msg[1].length == 0)
3784 || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3788 indication = GET_WORD(msg[1].info);
3792 case _DI_NEGOTIATE_B3:
3795 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3796 || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3798 dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3801 if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3803 dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3807 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3808 if (plci->fax_connect_info_length < len)
3810 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3811 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3813 if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3815 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3819 if (plci->fax_connect_info_length <= len)
3820 plci->fax_connect_info_buffer[len] = 0;
3821 len += 1 + plci->fax_connect_info_buffer[len];
3822 if (plci->fax_connect_info_length <= len)
3823 plci->fax_connect_info_buffer[len] = 0;
3824 len += 1 + plci->fax_connect_info_buffer[len];
3825 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3826 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3827 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3828 for (i = 0; i < fax_parms[7].length; i++)
3829 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3831 plci->fax_connect_info_length = len;
3832 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3833 start_internal_command (Id, plci, fax_edata_ack_command);
3840 /*------------------------------------------------------------------*/
3841 /* IDI callback function */
3842 /*------------------------------------------------------------------*/
3844 void callback(ENTITY * e)
3846 DIVA_CAPI_ADAPTER * a;
3857 dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3858 (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3860 a = &(adapter[(byte)e->user[0]]);
3861 plci = &(a->plci[e->user[1]]);
3862 no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3865 If new protocol code and new XDI is used then CAPI should work
3866 fully in accordance with IDI cpec an look on callback field instead
3867 of Rc field for return codes.
3869 if (((e->complete == 0xff) && no_cancel_rc) ||
3870 (e->Rc && !no_cancel_rc)) {
3876 if (e->user[0] & 0x8000)
3879 If REMOVE request was sent then we have to wait until
3880 return code with Id set to zero arrives.
3881 All other return codes should be ignored.
3887 dbug(1,dprintf("cancel RC in REMOVE state"));
3890 channel_flow_control_remove (plci);
3891 for (i = 0; i < 256; i++)
3893 if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3894 a->FlowControlIdTable[i] = 0;
3896 plci->nl_remove_id = 0;
3897 if (plci->rx_dma_descriptor > 0) {
3898 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3899 plci->rx_dma_descriptor = 0;
3904 a->FlowControlIdTable[ch] = e->Id;
3905 a->FlowControlSkipTable[ch] = 0;
3907 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3908 a->ch_flow_plci[ch] = plci->Id;
3914 Cancel return codes self, if feature was requested
3916 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3917 a->FlowControlIdTable[ch] = 0;
3918 if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3919 dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3924 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3926 a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3934 control_rc (plci, 0, rc, ch, 0, true);
3939 channel_x_on (plci, ch);
3940 if (plci->internal_command)
3941 control_rc (plci, req, rc, ch, 0, true);
3945 if (plci->nl_global_req)
3947 global_req = plci->nl_global_req;
3948 plci->nl_global_req = 0;
3949 if (rc != ASSIGN_OK) {
3951 if (plci->rx_dma_descriptor > 0) {
3952 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3953 plci->rx_dma_descriptor = 0;
3956 channel_xmit_xon (plci);
3957 control_rc (plci, 0, rc, ch, global_req, true);
3959 else if (plci->data_sent)
3961 channel_xmit_xon (plci);
3962 plci->data_sent = false;
3965 if (plci->internal_command)
3966 control_rc (plci, req, rc, ch, 0, true);
3970 channel_xmit_xon (plci);
3971 control_rc (plci, req, rc, ch, 0, true);
3979 If REMOVE request was sent then we have to wait until
3980 return code with Id set to zero arrives.
3981 All other return codes should be ignored.
3987 dbug(1,dprintf("cancel RC in REMOVE state"));
3990 plci->sig_remove_id = 0;
3993 if (plci->sig_global_req)
3995 global_req = plci->sig_global_req;
3996 plci->sig_global_req = 0;
3997 if (rc != ASSIGN_OK)
3999 channel_xmit_xon (plci);
4000 control_rc (plci, 0, rc, ch, global_req, false);
4004 channel_xmit_xon (plci);
4005 control_rc (plci, req, rc, ch, 0, false);
4009 Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4010 same callback. Also if new XDI and protocol code used then jump
4014 channel_xmit_xon(plci);
4015 goto capi_callback_suffix;
4019 channel_xmit_xon(plci);
4022 if (e->user[0] &0x8000) {
4023 byte Ind = e->Ind & 0x0f;
4025 if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4026 (a->ch_flow_plci[Ch] == plci->Id)) {
4027 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4028 dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4030 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4033 if ((e->RNR != 1) &&
4034 (a->ch_flow_plci[Ch] == plci->Id) &&
4035 (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4036 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4037 dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4045 capi_callback_suffix:
4047 while (!plci->req_in
4048 && !plci->internal_command
4049 && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4051 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4053 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4055 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4056 appl = *((APPL * *)(&((byte *)(plci->msg_in_queue))[j+i]));
4057 dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4058 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4059 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4061 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4062 plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4066 plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4068 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4070 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4071 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4073 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4075 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4076 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4078 i = api_put (appl, m);
4081 if (m->header.command == _DATA_B3_R)
4083 TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4085 dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4089 if (plci->li_notify_update)
4091 plci->li_notify_update = false;
4092 mixer_notify_update (plci, false);
4101 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4110 DIVA_CAPI_ADAPTER * a;
4113 byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4114 byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4117 dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4120 dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4121 if(plci->req_in!=plci->req_out)
4123 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4125 dbug(1,dprintf("req_1return"));
4128 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4130 plci->req_in = plci->req_in_start = plci->req_out = 0;
4131 dbug(1,dprintf("control_rc"));
4135 ncci = a->ch_ncci[ch];
4138 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4139 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4140 Number = plci->number;
4141 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));
4142 dbug(1,dprintf("channels=0x%x",plci->channels));
4143 if (plci_remove_check(plci))
4145 if(req==REMOVE && rc==ASSIGN_OK)
4147 sig_req(plci,HANGUP,0);
4148 sig_req(plci,REMOVE,0);
4153 switch(plci->command)
4156 dbug(1,dprintf("HoldRC=0x%x",rc));
4157 SSparms[1] = (byte)S_HOLD;
4160 plci->SuppState = IDLE;
4163 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4166 case C_RETRIEVE_REQ:
4167 dbug(1,dprintf("RetrieveRC=0x%x",rc));
4168 SSparms[1] = (byte)S_RETRIEVE;
4171 plci->SuppState = CALL_HELD;
4174 sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4178 dbug(1,dprintf("InfoRC=0x%x",rc));
4179 if(rc!=OK) Info=_WRONG_STATE;
4180 sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4184 dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4185 if (plci->State == INC_DIS_PENDING)
4187 if(plci->Sig.Id!=0xff)
4189 if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4190 || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4192 dbug(1,dprintf("No more IDs/Call_Req failed"));
4193 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4198 if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4199 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4201 else /* D-ch activation */
4203 if (rc != ASSIGN_OK)
4205 dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4206 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4211 sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4212 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4213 plci->State = INC_ACT_PENDING;
4217 case _CONNECT_I|RESPONSE:
4218 if (plci->State != INC_DIS_PENDING)
4219 plci->State = INC_CON_ACCEPT;
4223 if (plci->State == INC_DIS_PENDING)
4225 if(plci->Sig.Id!=0xff)
4227 plci->State = OUTG_DIS_PENDING;
4228 sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4241 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4244 ncci = get_ncci (plci, ch, 0);
4245 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4249 a->ncci_state[ncci] = INC_ACT_PENDING;
4250 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4251 sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4255 a->ncci_state[ncci] = OUTG_CON_PENDING;
4256 sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4260 case _CONNECT_B3_I|RESPONSE:
4264 /* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4267 case _DISCONNECT_B3_R:
4268 sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4271 case _MANUFACTURER_R:
4277 Info = _WRONG_IDENTIFIER;
4278 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4282 sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4290 else if (plci->internal_command)
4292 switch(plci->internal_command)
4298 if(rc==OK) /* command supported, wait for indication */
4305 /* Get Supported Services */
4306 case GETSERV_REQ_PEND:
4307 if(rc==OK) /* command supported, wait for indication */
4311 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4312 sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4316 case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
4317 case INTERR_NUMBERS_REQ_PEND:
4318 case CF_START_PEND: /* Call Forwarding Start pending */
4319 case CF_STOP_PEND: /* Call Forwarding Stop pending */
4320 case CCBS_REQUEST_REQ_PEND:
4321 case CCBS_DEACTIVATE_REQ_PEND:
4322 case CCBS_INTERROGATE_REQ_PEND:
4323 switch(plci->internal_command)
4325 case INTERR_DIVERSION_REQ_PEND:
4326 SSparms[1] = S_INTERROGATE_DIVERSION;
4328 case INTERR_NUMBERS_REQ_PEND:
4329 SSparms[1] = S_INTERROGATE_NUMBERS;
4332 SSparms[1] = S_CALL_FORWARDING_START;
4335 SSparms[1] = S_CALL_FORWARDING_STOP;
4337 case CCBS_REQUEST_REQ_PEND:
4338 SSparms[1] = S_CCBS_REQUEST;
4340 case CCBS_DEACTIVATE_REQ_PEND:
4341 SSparms[1] = S_CCBS_DEACTIVATE;
4343 case CCBS_INTERROGATE_REQ_PEND:
4344 SSparms[1] = S_CCBS_INTERROGATE;
4347 if(global_req==ASSIGN)
4349 dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4352 if(!plci->appl) break;
4353 if(rc==ISDN_GUARD_REJ)
4355 Info = _CAPI_GUARD_ERROR;
4359 Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4361 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4362 plci->number,"wws",Info,(word)3,SSparms);
4363 if(Info) plci_remove(plci);
4366 /* 3pty conference pending */
4368 if(!plci->relatedPTYPLCI) break;
4369 rplci = plci->relatedPTYPLCI;
4370 SSparms[1] = plci->ptyState;
4371 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4372 if(rplci->tel) rId|=EXT_CONTROLLER;
4375 Info = 0x300E; /* not supported */
4376 plci->relatedPTYPLCI = NULL;
4380 _FACILITY_R|CONFIRM,
4383 "wws",Info,(word)3,SSparms);
4386 /* Explicit Call Transfer pending */
4388 dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4389 if(!plci->relatedPTYPLCI) break;
4390 rplci = plci->relatedPTYPLCI;
4392 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4393 if(rplci->tel) rId|=EXT_CONTROLLER;
4396 Info = 0x300E; /* not supported */
4397 plci->relatedPTYPLCI = NULL;
4401 _FACILITY_R|CONFIRM,
4404 "wws",Info,(word)3,SSparms);
4407 case _MANUFACTURER_R:
4408 dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4409 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4411 dbug(1,dprintf("No more IDs"));
4412 sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4413 plci_remove(plci); /* after codec init, internal codec commands pending */
4418 dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4419 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4421 dbug(1,dprintf("No more IDs"));
4422 sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4423 plci_remove(plci); /* after codec init, internal codec commands pending */
4427 case PERM_COD_HOOK: /* finished with Hook_Ind */
4431 dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4432 plci->internal_command = PERM_COD_CONN_PEND;
4435 case PERM_COD_ASSIGN:
4436 dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4437 if(rc!=ASSIGN_OK) break;
4438 sig_req(plci,CALL_REQ,0);
4440 plci->internal_command = PERM_COD_CALL;
4443 /* Null Call Reference Request pending */
4445 dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4446 if(global_req==ASSIGN)
4454 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4455 appl->NullCREnable = false;
4459 else if(req==NCR_FACILITY)
4463 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4467 sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4468 appl->NullCREnable = false;
4477 if(a->ncci_state[ncci]==CONNECTED)
4479 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4480 cleanup_ncci_data (plci, ncci);
4481 nl_req_ncci(plci,N_DISC,(byte)ncci);
4488 if (plci->State == INC_DIS_PENDING)
4490 sig_req(plci,CALL_REQ,0);
4492 plci->State=OUTG_CON_PENDING;
4496 case MWI_ACTIVATE_REQ_PEND:
4497 case MWI_DEACTIVATE_REQ_PEND:
4498 if(global_req == ASSIGN && rc==ASSIGN_OK)
4500 dbug(1,dprintf("MWI_REQ assigned"));
4507 Info = 0x2007; /* Illegal message parameter coding */
4508 dbug(1,dprintf("MWI_REQ invalid parameter"));
4512 Info = 0x300B; /* not supported */
4513 dbug(1,dprintf("MWI_REQ not supported"));
4515 /* 0x3010: Request not allowed in this state */
4516 PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4519 if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4521 PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4523 else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4525 if(plci->cr_enquiry)
4528 _FACILITY_R|CONFIRM,
4531 "wws",Info,(word)3,SSparms);
4532 if(rc!=OK) plci_remove(plci);
4537 _FACILITY_R|CONFIRM,
4540 "wws",Info,(word)3,SSparms);
4544 case CONF_BEGIN_REQ_PEND:
4545 case CONF_ADD_REQ_PEND:
4546 case CONF_SPLIT_REQ_PEND:
4547 case CONF_DROP_REQ_PEND:
4548 case CONF_ISOLATE_REQ_PEND:
4549 case CONF_REATTACH_REQ_PEND:
4550 dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4551 if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4554 switch(plci->internal_command)
4556 case CONF_BEGIN_REQ_PEND:
4557 SSparms[1] = S_CONF_BEGIN;
4559 case CONF_ADD_REQ_PEND:
4560 SSparms[1] = S_CONF_ADD;
4561 rplci = plci->relatedPTYPLCI;
4562 rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4564 case CONF_SPLIT_REQ_PEND:
4565 SSparms[1] = S_CONF_SPLIT;
4567 case CONF_DROP_REQ_PEND:
4568 SSparms[1] = S_CONF_DROP;
4570 case CONF_ISOLATE_REQ_PEND:
4571 SSparms[1] = S_CONF_ISOLATE;
4573 case CONF_REATTACH_REQ_PEND:
4574 SSparms[1] = S_CONF_REATTACH;
4580 Info = 0x300E; /* not supported */
4581 plci->relatedPTYPLCI = NULL;
4585 _FACILITY_R|CONFIRM,
4588 "wws",Info,(word)3,SSparms);
4591 case VSWITCH_REQ_PEND:
4594 if(plci->relatedPTYPLCI)
4596 plci->relatedPTYPLCI->vswitchstate=0;
4597 plci->relatedPTYPLCI->vsprot=0;
4598 plci->relatedPTYPLCI->vsprotdialect=0;
4600 plci->vswitchstate=0;
4602 plci->vsprotdialect=0;
4606 if(plci->relatedPTYPLCI &&
4607 plci->vswitchstate==1 &&
4608 plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4609 plci->vswitchstate=3;
4613 /* Call Deflection Request pending (SSCT) */
4615 SSparms[1] = S_CALL_DEFLECTION;
4618 Info = 0x300E; /* not supported */
4619 plci->appl->CDEnable = 0;
4621 sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4622 plci->number,"wws",Info,(word)3,SSparms);
4625 case RTP_CONNECT_B3_REQ_COMMAND_2:
4628 ncci = get_ncci (plci, ch, 0);
4629 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4631 a->ncci_state[ncci] = OUTG_CON_PENDING;
4635 if (plci->internal_command_queue[0])
4637 (*(plci->internal_command_queue[0]))(Id, plci, rc);
4638 if (plci->internal_command)
4643 next_internal_command (Id, plci);
4648 Id = ((word)plci->Id<<8)|plci->adapter->Id;
4649 if(plci->tel) Id|=EXT_CONTROLLER;
4651 switch(plci->internal_command)
4656 case START_L1_SIG_ASSIGN_PEND:
4657 case REM_L1_SIG_ASSIGN_PEND:
4658 if(global_req == ASSIGN)
4664 dbug(1,dprintf("***L1 Req rem PLCI"));
4665 plci->internal_command = 0;
4666 sig_req(plci,REMOVE,0);
4671 /* Call Deflection Request pending, just no appl ptr assigned */
4673 SSparms[1] = S_CALL_DEFLECTION;
4676 Info = 0x300E; /* not supported */
4678 for(i=0; i<max_appl; i++)
4680 if(application[i].CDEnable)
4682 if(!application[i].Id) application[i].CDEnable = 0;
4685 sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4686 plci->number,"wws",Info,(word)3,SSparms);
4687 if(Info) application[i].CDEnable = 0;
4691 plci->internal_command = 0;
4694 case PERM_COD_HOOK: /* finished with Hook_Ind */
4698 plci->internal_command = PERM_COD_CONN_PEND;
4699 dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4702 case PERM_COD_ASSIGN:
4703 dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4704 plci->internal_command = 0;
4705 if(rc!=ASSIGN_OK) break;
4706 plci->internal_command = PERM_COD_CALL;
4707 sig_req(plci,CALL_REQ,0);
4711 case LISTEN_SIG_ASSIGN_PEND:
4714 plci->internal_command = 0;
4715 dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4716 add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
4717 sig_req(plci,INDICATE_REQ,0);
4722 dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4730 if(global_req == ASSIGN)
4734 sig_req(plci,LAW_REQ,0);
4736 dbug(1,dprintf("Auto-Law assigned"));
4740 dbug(1,dprintf("Auto-Law assign failed"));
4741 a->automatic_law = 3;
4742 plci->internal_command = 0;
4743 a->automatic_lawPLCI = NULL;
4747 else if(req == LAW_REQ && rc==OK)
4749 dbug(1,dprintf("Auto-Law initiated"));
4750 a->automatic_law = 2;
4751 plci->internal_command = 0;
4755 dbug(1,dprintf("Auto-Law not supported"));
4756 a->automatic_law = 3;
4757 plci->internal_command = 0;
4758 sig_req(plci,REMOVE,0);
4760 a->automatic_lawPLCI = NULL;
4764 plci_remove_check(plci);
4768 static void data_rc(PLCI *plci, byte ch)
4771 DIVA_CAPI_ADAPTER * a;
4778 TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4780 ncci = a->ch_ncci[ch];
4781 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4783 ncci_ptr = &(a->ncci[ncci]);
4784 dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4785 if (ncci_ptr->data_pending)
4787 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4788 if (!(data->Flags &4) && a->ncci_state[ncci])
4790 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4791 if(plci->tel) Id|=EXT_CONTROLLER;
4792 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4793 "ww",data->Handle,0);
4795 (ncci_ptr->data_out)++;
4796 if (ncci_ptr->data_out == MAX_DATA_B3)
4797 ncci_ptr->data_out = 0;
4798 (ncci_ptr->data_pending)--;
4804 static void data_ack(PLCI *plci, byte ch)
4807 DIVA_CAPI_ADAPTER * a;
4812 ncci = a->ch_ncci[ch];
4813 ncci_ptr = &(a->ncci[ncci]);
4814 if (ncci_ptr->data_ack_pending)
4816 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4818 Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4819 if(plci->tel) Id|=EXT_CONTROLLER;
4820 sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4821 "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4823 (ncci_ptr->data_ack_out)++;
4824 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4825 ncci_ptr->data_ack_out = 0;
4826 (ncci_ptr->data_ack_pending)--;
4830 static void sig_ind(PLCI *plci)
4840 DIVA_CAPI_ADAPTER * a;
4841 API_PARSE saved_parms[MAX_MSG_PARMS+1];
4842 #define MAXPARMSIDS 31
4843 byte * parms[MAXPARMSIDS];
4845 byte * multi_fac_parms[MAX_MULTI_IE];
4846 byte * multi_pi_parms [MAX_MULTI_IE];
4847 byte * multi_ssext_parms [MAX_MULTI_IE];
4848 byte * multi_CiPN_parms [MAX_MULTI_IE];
4850 byte * multi_vswitch_parms [MAX_MULTI_IE];
4857 byte *esc_profile = "";
4860 PLCI * tplci = NULL;
4861 byte chi[] = "\x02\x18\x01";
4862 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
4863 byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4864 /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4865 /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4866 /* SMSG is situated at the end because its 0 (for compatibility reasons */
4867 /* (see Info_Mask Bit 4, first IE. then the message type) */
4869 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4870 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4871 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4872 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4873 /* 14 FTY repl by ESC_CHI */
4874 /* 18 PI repl by ESC_LAW */
4875 /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4876 word multi_fac_id[] = {1, FTY};
4877 word multi_pi_id[] = {1, PI};
4878 word multi_CiPN_id[] = {1, OAD};
4879 word multi_ssext_id[] = {1, ESC_SSEXT};
4881 word multi_vswitch_id[] = {1, ESC_VSWITCH};
4885 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4886 byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4887 byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4888 byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4889 byte force_mt_info = false;
4895 Id = ((word)plci->Id<<8)|a->Id;
4896 PUT_WORD(&SS_Ind[4],0x0000);
4898 if (plci->sig_remove_id)
4900 plci->Sig.RNR = 2; /* discard */
4901 dbug(1,dprintf("SIG discard while remove pending"));
4904 if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4905 dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4906 Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4907 if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4912 if(plci->Sig.Ind==HANGUP && plci->channels)
4915 plci->hangup_flow_ctrl_timer++;
4916 /* recover the network layer after timeout */
4917 if(plci->hangup_flow_ctrl_timer==100)
4919 dbug(1,dprintf("Exceptional disc"));
4921 plci->hangup_flow_ctrl_timer = 0;
4922 for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4924 if (a->ncci_plci[ncci] == plci->Id)
4926 cleanup_ncci_data (plci, ncci);
4927 if(plci->channels)plci->channels--;
4929 sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4933 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4940 /* do first parse the info with no OAD in, because OAD will be converted */
4941 /* first the multiple facility IE, then mult. progress ind. */
4942 /* then the parameters for the info_ind + conn_ind */
4943 IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4944 IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4945 IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4947 IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4949 IndParse(plci,parms_id,parms,0);
4950 IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4951 esc_chi = parms[14];
4952 esc_law = parms[18];
4953 pty_cai = parms[24];
4955 esc_profile = parms[27];
4956 if(esc_cr[0] && plci)
4958 if(plci->cr_enquiry && plci->appl)
4960 plci->cr_enquiry = false;
4963 /* b = total length */
4964 /* b = indication type */
4965 /* b = length of all IEs */
4967 /* S = IE1 length + cont. */
4969 /* S = IE2 length + cont. */
4974 "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4975 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);
4978 /* create the additional info structure */
4979 add_i[1] = parms[15]; /* KEY of additional info */
4980 add_i[2] = parms[11]; /* UUI of additional info */
4981 ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4983 /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
4984 /* indication returns by the card if requested by the function */
4985 /* AutomaticLaw() after driver init */
4986 if (a->automatic_law<4)
4990 dbug(0,dprintf("u-Law selected"));
4994 dbug(0,dprintf("a-Law selected"));
4997 a->automatic_law = 4;
4998 if(plci==a->automatic_lawPLCI) {
4999 plci->internal_command = 0;
5000 sig_req(plci,REMOVE,0);
5002 a->automatic_lawPLCI = NULL;
5007 dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5008 UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
5009 GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
5010 GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
5012 a->profile.Global_Options &= 0x000000ffL;
5013 a->profile.B1_Protocols &= 0x000003ffL;
5014 a->profile.B2_Protocols &= 0x00001fdfL;
5015 a->profile.B3_Protocols &= 0x000000b7L;
5017 a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
5018 GL_BCHANNEL_OPERATION_SUPPORTED;
5019 a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
5020 a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
5021 a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5022 a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5023 a->man_profile.private_options = 0;
5025 if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5027 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5028 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5032 if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5033 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5034 a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5035 a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5038 if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5039 a->man_profile.private_options |= 1L << PRIVATE_T38;
5042 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5043 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5046 if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5047 a->man_profile.private_options |= 1L << PRIVATE_V18;
5050 if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5051 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5054 if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5055 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5058 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5059 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5062 if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5063 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5066 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5067 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5072 a->profile.Global_Options &= 0x0000007fL;
5073 a->profile.B1_Protocols &= 0x000003dfL;
5074 a->profile.B2_Protocols &= 0x00001adfL;
5075 a->profile.B3_Protocols &= 0x000000b7L;
5076 a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5078 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5079 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5081 a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5083 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5084 dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5085 UnMapController (a->Id), a->profile.Global_Options,
5086 a->profile.B1_Protocols, a->profile.B2_Protocols,
5087 a->profile.B3_Protocols, a->manufacturer_features));
5089 /* codec plci for the handset/hook state support is just an internal id */
5090 if(plci!=a->AdvCodecPLCI)
5092 force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5093 force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5094 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5095 SendInfo(plci,Id, parms, force_mt_info);
5097 VSwitchReqInd(plci,Id,multi_vswitch_parms);
5101 /* switch the codec to the b-channel */
5102 if(esc_chi[0] && plci && !plci->SuppState){
5103 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5104 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5105 dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5106 if(plci->tel==ADV_VOICE && plci->appl) {
5107 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5111 if(plci->appl) Number = plci->appl->Number++;
5113 switch(plci->Sig.Ind) {
5114 /* Response to Get_Supported_Services request */
5116 dbug(1,dprintf("S_Supported"));
5117 if(!plci->appl) break;
5120 PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5124 PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5126 PUT_WORD (&CF_Ind[1], 0);
5127 PUT_WORD (&CF_Ind[4], 0);
5128 sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5132 /* Supplementary Service rejected */
5134 dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5135 if(!pty_cai[0]) break;
5140 case THREE_PTY_BEGIN:
5141 if(!plci->relatedPTYPLCI) break;
5142 tplci = plci->relatedPTYPLCI;
5143 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5144 if(tplci->tel) rId|=EXT_CONTROLLER;
5145 if(pty_cai[5]==ECT_EXECUTE)
5147 PUT_WORD(&SS_Ind[1],S_ECT);
5149 plci->vswitchstate=0;
5150 plci->relatedPTYPLCI->vswitchstate=0;
5155 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5157 if(pty_cai[2]!=0xff)
5159 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5163 PUT_WORD(&SS_Ind[4],0x300E);
5165 plci->relatedPTYPLCI = NULL;
5167 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5170 case CALL_DEFLECTION:
5171 if(pty_cai[2]!=0xff)
5173 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5177 PUT_WORD(&SS_Ind[4],0x300E);
5179 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5180 for(i=0; i<max_appl; i++)
5182 if(application[i].CDEnable)
5184 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5185 application[i].CDEnable = false;
5190 case DEACTIVATION_DIVERSION:
5191 case ACTIVATION_DIVERSION:
5192 case DIVERSION_INTERROGATE_CFU:
5193 case DIVERSION_INTERROGATE_CFB:
5194 case DIVERSION_INTERROGATE_CFNR:
5195 case DIVERSION_INTERROGATE_NUM:
5197 case CCBS_DEACTIVATE:
5198 case CCBS_INTERROGATE:
5199 if(!plci->appl) break;
5200 if(pty_cai[2]!=0xff)
5202 PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5206 PUT_WORD(&Interr_Err_Ind[4],0x300E);
5210 case DEACTIVATION_DIVERSION:
5211 dbug(1,dprintf("Deact_Div"));
5212 Interr_Err_Ind[0]=0x9;
5213 Interr_Err_Ind[3]=0x6;
5214 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5216 case ACTIVATION_DIVERSION:
5217 dbug(1,dprintf("Act_Div"));
5218 Interr_Err_Ind[0]=0x9;
5219 Interr_Err_Ind[3]=0x6;
5220 PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5222 case DIVERSION_INTERROGATE_CFU:
5223 case DIVERSION_INTERROGATE_CFB:
5224 case DIVERSION_INTERROGATE_CFNR:
5225 dbug(1,dprintf("Interr_Div"));
5226 Interr_Err_Ind[0]=0xa;
5227 Interr_Err_Ind[3]=0x7;
5228 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5230 case DIVERSION_INTERROGATE_NUM:
5231 dbug(1,dprintf("Interr_Num"));
5232 Interr_Err_Ind[0]=0xa;
5233 Interr_Err_Ind[3]=0x7;
5234 PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5237 dbug(1,dprintf("CCBS Request"));
5238 Interr_Err_Ind[0]=0xd;
5239 Interr_Err_Ind[3]=0xa;
5240 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5242 case CCBS_DEACTIVATE:
5243 dbug(1,dprintf("CCBS Deactivate"));
5244 Interr_Err_Ind[0]=0x9;
5245 Interr_Err_Ind[3]=0x6;
5246 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5248 case CCBS_INTERROGATE:
5249 dbug(1,dprintf("CCBS Interrogate"));
5250 Interr_Err_Ind[0]=0xb;
5251 Interr_Err_Ind[3]=0x8;
5252 PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5255 PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5256 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5259 case ACTIVATION_MWI:
5260 case DEACTIVATION_MWI:
5261 if(pty_cai[5]==ACTIVATION_MWI)
5263 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5265 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5267 if(pty_cai[2]!=0xff)
5269 PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5273 PUT_WORD(&SS_Ind[4],0x300E);
5276 if(plci->cr_enquiry)
5278 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5283 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5286 case CONF_ADD: /* ERROR */
5296 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5302 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5303 plci->ptyState = CONNECTED;
5308 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5309 plci->ptyState = CONNECTED;
5314 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5315 plci->ptyState = CONNECTED;
5318 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5319 plci->relatedPTYPLCI = NULL;
5320 tplci=plci->relatedPTYPLCI;
5321 if(tplci) tplci->ptyState = CONNECTED;
5322 plci->ptyState = CONNECTED;
5326 if(pty_cai[2]!=0xff)
5328 PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5332 PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5333 within the required time */
5336 PUT_DWORD(&CONF_Ind[6],0x0);
5337 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5342 /* Supplementary Service indicates success */
5344 dbug(1,dprintf("Service_Ind"));
5345 PUT_WORD (&CF_Ind[4], 0);
5349 case THREE_PTY_BEGIN:
5351 if(!plci->relatedPTYPLCI) break;
5352 tplci = plci->relatedPTYPLCI;
5353 rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5354 if(tplci->tel) rId|=EXT_CONTROLLER;
5355 if(pty_cai[5]==ECT_EXECUTE)
5357 PUT_WORD(&SS_Ind[1],S_ECT);
5359 if(plci->vswitchstate!=3)
5362 plci->ptyState = IDLE;
5363 plci->relatedPTYPLCI = NULL;
5368 dbug(1,dprintf("ECT OK"));
5369 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5376 switch (plci->ptyState)
5379 plci->ptyState = CONNECTED;
5380 dbug(1,dprintf("3PTY ON"));
5384 plci->ptyState = IDLE;
5385 plci->relatedPTYPLCI = NULL;
5387 dbug(1,dprintf("3PTY OFF"));
5390 PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5391 sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5395 case CALL_DEFLECTION:
5396 PUT_WORD(&SS_Ind[1],pty_cai[5]);
5397 for(i=0; i<max_appl; i++)
5399 if(application[i].CDEnable)
5401 if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5402 application[i].CDEnable = false;
5407 case DEACTIVATION_DIVERSION:
5408 case ACTIVATION_DIVERSION:
5409 if(!plci->appl) break;
5410 PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5411 PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5412 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5416 case DIVERSION_INTERROGATE_CFU:
5417 case DIVERSION_INTERROGATE_CFB:
5418 case DIVERSION_INTERROGATE_CFNR:
5419 case DIVERSION_INTERROGATE_NUM:
5421 case CCBS_DEACTIVATE:
5422 case CCBS_INTERROGATE:
5423 if(!plci->appl) break;
5426 case DIVERSION_INTERROGATE_CFU:
5427 case DIVERSION_INTERROGATE_CFB:
5428 case DIVERSION_INTERROGATE_CFNR:
5429 dbug(1,dprintf("Interr_Div"));
5430 PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5431 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5433 case DIVERSION_INTERROGATE_NUM:
5434 dbug(1,dprintf("Interr_Num"));
5435 PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5436 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5439 dbug(1,dprintf("CCBS Request"));
5440 PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5441 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5443 case CCBS_DEACTIVATE:
5444 dbug(1,dprintf("CCBS Deactivate"));
5445 PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5446 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5448 case CCBS_INTERROGATE:
5449 dbug(1,dprintf("CCBS Interrogate"));
5450 PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5451 pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5454 PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5455 PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5456 sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5460 case ACTIVATION_MWI:
5461 case DEACTIVATION_MWI:
5462 if(pty_cai[5]==ACTIVATION_MWI)
5464 PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5466 else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5467 if(plci->cr_enquiry)
5469 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5474 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5477 case MWI_INDICATION:
5478 if(pty_cai[0]>=0x12)
5480 PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5481 pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5482 pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5483 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5485 if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5487 sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5491 else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5496 for(i=0; i<max_appl; i++)
5498 if(a->Notification_Mask[i]&SMASK_MWI)
5500 sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5508 facility[2]= 0; /* returncode */
5510 else facility[2]= 0xff;
5515 facility[2]= 0xff; /* returncode */
5518 facility[1]= MWI_RESPONSE; /* Function */
5519 add_p(plci,CAI,facility);
5520 add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5521 sig_req(plci,S_SERVICE,0);
5524 next_internal_command (Id, plci);
5526 case CONF_ADD: /* OK */
5531 case CONF_PARTYDISC:
5537 PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5541 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5545 PUT_DWORD(&CONF_Ind[6],0x0);
5549 PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5554 PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5559 PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5564 PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5566 PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5567 tplci=plci->relatedPTYPLCI;
5568 if(tplci) tplci->ptyState = CONNECTED;
5570 case CONF_PARTYDISC:
5573 PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5575 PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5578 plci->ptyState = CONNECTED;
5579 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5581 case CCBS_INFO_RETAIN:
5582 case CCBS_ERASECALLLINKAGEID:
5583 case CCBS_STOP_ALERTING:
5588 case CCBS_INFO_RETAIN:
5589 PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5591 case CCBS_STOP_ALERTING:
5592 PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5594 case CCBS_ERASECALLLINKAGEID:
5595 PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5603 PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5605 if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5607 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5611 for(i=0; i<max_appl; i++)
5612 if(a->Notification_Mask[i]&SMASK_CCBS)
5613 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5622 i = _L3_CAUSE | cau[2];
5623 if(cau[2]==0) i = 0x3603;
5629 PUT_WORD(&SS_Ind[1],S_HOLD);
5630 PUT_WORD(&SS_Ind[4],i);
5631 if(plci->SuppState == HOLD_REQUEST)
5633 plci->SuppState = IDLE;
5634 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5639 if(plci->SuppState == HOLD_REQUEST)
5641 plci->SuppState = CALL_HELD;
5642 CodecIdCheck(a, plci);
5643 start_internal_command (Id, plci, hold_save_command);
5647 case CALL_RETRIEVE_REJ:
5651 i = _L3_CAUSE | cau[2];
5652 if(cau[2]==0) i = 0x3603;
5658 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5659 PUT_WORD(&SS_Ind[4],i);
5660 if(plci->SuppState == RETRIEVE_REQUEST)
5662 plci->SuppState = CALL_HELD;
5663 CodecIdCheck(a, plci);
5664 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5668 case CALL_RETRIEVE_ACK:
5669 PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5670 if(plci->SuppState == RETRIEVE_REQUEST)
5672 plci->SuppState = IDLE;
5673 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5674 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5677 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5678 dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5679 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5680 if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5682 dbug(1,dprintf("Get B-ch"));
5683 start_internal_command (Id, plci, retrieve_restore_command);
5686 sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5689 start_internal_command (Id, plci, retrieve_restore_command);
5694 if(plci->State != LISTENING) {
5695 sig_req(plci,HANGUP,0);
5699 cip = find_cip(a,parms[4],parms[6]);
5701 dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5702 clear_c_ind_mask (plci);
5703 if (!remove_started && !a->adapter_disabled)
5705 set_c_ind_mask_bit (plci, MAX_APPL);
5706 group_optimization(a, plci);
5707 for(i=0; i<max_appl; i++) {
5708 if(application[i].Id
5709 && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5710 && CPN_filter_ok(parms[0],a,i)
5711 && test_group_ind_mask_bit (plci, i) ) {
5712 dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5713 set_c_ind_mask_bit (plci, i);
5714 dump_c_ind_mask (plci);
5715 plci->State = INC_CON_PENDING;
5716 plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5717 CALL_DIR_IN | CALL_DIR_ANSWER;
5719 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5720 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5722 /* if a listen on the ext controller is done, check if hook states */
5723 /* are supported or if just a on board codec must be activated */
5724 if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5725 if(a->profile.Global_Options & HANDSET)
5726 plci->tel = ADV_VOICE;
5727 else if(a->profile.Global_Options & ON_BOARD_CODEC)
5729 if(plci->tel) Id|=EXT_CONTROLLER;
5730 a->codec_listen[i] = plci;
5733 sendf(&application[i],_CONNECT_I,Id,0,
5734 "wSSSSSSSbSSSSS", cip, /* CIP */
5735 parms[0], /* CalledPartyNumber */
5736 multi_CiPN_parms[0], /* CallingPartyNumber */
5737 parms[2], /* CalledPartySubad */
5738 parms[3], /* CallingPartySubad */
5739 parms[4], /* BearerCapability */
5740 parms[5], /* LowLC */
5741 parms[6], /* HighLC */
5742 ai_len, /* nested struct add_i */
5743 add_i[0], /* B channel info */
5744 add_i[1], /* keypad facility */
5745 add_i[2], /* user user data */
5746 add_i[3], /* nested facility */
5747 multi_CiPN_parms[1] /* second CiPN(SCR) */
5749 SendSSExtInd(&application[i],
5753 SendSetupInfo(&application[i],
5757 SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5760 clear_c_ind_mask_bit (plci, MAX_APPL);
5761 dump_c_ind_mask (plci);
5763 if(c_ind_mask_empty (plci)) {
5764 sig_req(plci,HANGUP,0);
5768 plci->notifiedcall = 0;
5773 case CALL_PEND_NOTIFY:
5774 plci->notifiedcall = 1;
5780 if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5782 if(plci->internal_command==PERM_COD_CONN_PEND)
5784 if(plci->State==ADVANCED_VOICE_NOSIG)
5786 dbug(1,dprintf("***Codec OK"));
5787 if(a->AdvSignalPLCI)
5789 tplci = a->AdvSignalPLCI;
5790 if(tplci->spoofed_msg)
5792 dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5794 tplci->internal_command = 0;
5795 x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5796 switch (tplci->spoofed_msg)
5799 tplci->command = _CONNECT_I|RESPONSE;
5800 api_load_msg (&tplci->saved_msg, saved_parms);
5801 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5802 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5804 /* early B3 connect (CIP mask bit 9) no release after a disc */
5805 add_p(tplci,LLI,"\x01\x01");
5807 add_s(tplci, CONN_NR, &saved_parms[2]);
5808 add_s(tplci, LLC, &saved_parms[4]);
5809 add_ai(tplci, &saved_parms[5]);
5810 tplci->State = INC_CON_ACCEPT;
5811 sig_req(tplci, CALL_RES,0);
5815 case AWAITING_SELECT_B:
5816 dbug(1,dprintf("Select_B continue"));
5817 start_internal_command (x_Id, tplci, select_b_command);
5820 case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5823 dbug(1,dprintf("No SigID!"));
5824 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5828 tplci->command = _MANUFACTURER_R;
5829 api_load_msg (&tplci->saved_msg, saved_parms);
5830 dir = saved_parms[2].info[0];
5832 sig_req(tplci,CALL_REQ,0);
5835 sig_req(tplci,LISTEN_REQ,0);
5838 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5841 case (CALL_REQ|AWAITING_MANUF_CON):
5842 sig_req(tplci,CALL_REQ,0);
5849 dbug(1,dprintf("No SigID!"));
5850 sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5854 tplci->command = _CONNECT_R;
5855 api_load_msg (&tplci->saved_msg, saved_parms);
5856 add_s(tplci,CPN,&saved_parms[1]);
5857 add_s(tplci,DSA,&saved_parms[3]);
5858 add_ai(tplci,&saved_parms[9]);
5859 sig_req(tplci,CALL_REQ,0);
5864 tplci->command = C_RETRIEVE_REQ;
5865 sig_req(tplci,CALL_RETRIEVE,0);
5869 tplci->spoofed_msg = 0;
5870 if (tplci->internal_command == 0)
5871 next_internal_command (x_Id, tplci);
5874 next_internal_command (Id, plci);
5877 dbug(1,dprintf("***Codec Hook Init Req"));
5878 plci->internal_command = PERM_COD_HOOK;
5879 add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
5880 sig_req(plci,TEL_CTRL,0);
5884 else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
5885 && plci->State!=INC_ACT_PENDING)
5887 mixer_set_bchannel_id_esc (plci, plci->b_channel);
5888 if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5890 chi[2] = plci->b_channel;
5891 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5893 sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5894 plci->State = INC_ACT_PENDING;
5900 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5901 if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5902 switch (ie[1]&0x91) {
5903 case 0x80: /* hook off */
5905 if(plci->internal_command==PERM_COD_HOOK)
5907 dbug(1,dprintf("init:hook_off"));
5908 plci->hook_state = ie[1];
5909 next_internal_command (Id, plci);
5912 else /* ignore doubled hook indications */
5914 if( ((plci->hook_state)&0xf0)==0x80)
5916 dbug(1,dprintf("ignore hook"));
5919 plci->hook_state = ie[1]&0x91;
5921 /* check for incoming call pending */
5922 /* and signal '+'.Appl must decide */
5923 /* with connect_res if call must */
5924 /* accepted or not */
5925 for(i=0, tplci=NULL;i<max_appl;i++){
5926 if(a->codec_listen[i]
5927 && (a->codec_listen[i]->State==INC_CON_PENDING
5928 ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5929 tplci = a->codec_listen[i];
5930 tplci->appl = &application[i];
5933 /* no incoming call, do outgoing call */
5934 /* and signal '+' if outg. setup */
5935 if(!a->AdvSignalPLCI && !tplci){
5936 if((i=get_plci(a))) {
5937 a->AdvSignalPLCI = &a->plci[i-1];
5938 tplci = a->AdvSignalPLCI;
5939 tplci->tel = ADV_VOICE;
5940 PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5941 if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5942 /* early B3 connect (CIP mask bit 9) no release after a disc */
5943 add_p(tplci,LLI,"\x01\x01");
5945 add_p(tplci, CAI, voice_cai);
5946 add_p(tplci, OAD, a->TelOAD);
5947 add_p(tplci, OSA, a->TelOSA);
5948 add_p(tplci,SHIFT|6,NULL);
5949 add_p(tplci,SIN,"\x02\x01\x00");
5950 add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5951 sig_req(tplci,ASSIGN,DSIG_ID);
5952 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5953 a->AdvSignalPLCI->command = 0;
5954 tplci->appl = a->AdvSignalAppl;
5955 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5962 Id = ((word)tplci->Id<<8)|a->Id;
5968 "ws", (word)0, "\x01+");
5971 case 0x90: /* hook on */
5973 if(plci->internal_command==PERM_COD_HOOK)
5975 dbug(1,dprintf("init:hook_on"));
5976 plci->hook_state = ie[1]&0x91;
5977 next_internal_command (Id, plci);
5980 else /* ignore doubled hook indications */
5982 if( ((plci->hook_state)&0xf0)==0x90) break;
5983 plci->hook_state = ie[1]&0x91;
5985 /* hangup the adv. voice call and signal '-' to the appl */
5986 if(a->AdvSignalPLCI) {
5987 Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5988 if(plci->tel) Id|=EXT_CONTROLLER;
5989 sendf(a->AdvSignalAppl,
5993 "ws", (word)0, "\x01-");
5994 a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5995 a->AdvSignalPLCI->command = 0;
5996 sig_req(a->AdvSignalPLCI,HANGUP,0);
5997 send_req(a->AdvSignalPLCI);
6005 clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
6006 PUT_WORD(&resume_cau[4],GOOD);
6007 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6011 clear_c_ind_mask (plci);
6013 if (plci->NL.Id && !plci->nl_remove_id) {
6014 mixer_remove (plci);
6015 nl_req_ncci(plci,REMOVE,0);
6017 if (!plci->sig_remove_id) {
6018 plci->internal_command = 0;
6019 sig_req(plci,REMOVE,0);
6022 if(!plci->channels) {
6023 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6024 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6032 plci->hangup_flow_ctrl_timer=0;
6033 if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6036 i = _L3_CAUSE | cau[2];
6037 if(cau[2]==0) i = 0;
6038 else if(cau[2]==8) i = _L1_ERROR;
6039 else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6040 else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6046 if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6048 for(i=0; i<max_appl; i++)
6050 if(test_c_ind_mask_bit (plci, i))
6051 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6056 clear_c_ind_mask (plci);
6060 if (plci->State == LISTENING)
6062 plci->notifiedcall=0;
6065 plci->State = INC_DIS_PENDING;
6066 if(c_ind_mask_empty (plci))
6069 if (plci->NL.Id && !plci->nl_remove_id)
6071 mixer_remove (plci);
6072 nl_req_ncci(plci,REMOVE,0);
6074 if (!plci->sig_remove_id)
6076 plci->internal_command = 0;
6077 sig_req(plci,REMOVE,0);
6084 /* collision of DISCONNECT or CONNECT_RES with HANGUP can */
6085 /* result in a second HANGUP! Don't generate another */
6087 if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6089 if(plci->State==RESUMING)
6091 PUT_WORD(&resume_cau[4],i);
6092 sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6094 plci->State = INC_DIS_PENDING;
6095 sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6101 SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6105 VSwitchReqInd(plci,Id,multi_vswitch_parms);
6108 if(plci->relatedPTYPLCI &&
6109 plci->vswitchstate==3 &&
6110 plci->relatedPTYPLCI->vswitchstate==3 &&
6111 parms[MAXPARMSIDS-1][0])
6113 add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6114 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6115 send_req(plci->relatedPTYPLCI);
6117 else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6124 static void SendSetupInfo(APPL * appl, PLCI * plci, dword Id, byte * * parms, byte Info_Sent_Flag)
6129 byte * Info_Element;
6132 dbug(1,dprintf("SetupInfo"));
6134 for(i=0; i<MAXPARMSIDS; i++) {
6141 dbug(1,dprintf("CPN "));
6142 Info_Number = 0x0070;
6144 Info_Sent_Flag = true;
6146 case 8: /* display */
6147 dbug(1,dprintf("display(%d)",i));
6148 Info_Number = 0x0028;
6150 Info_Sent_Flag = true;
6152 case 16: /* Channel Id */
6153 dbug(1,dprintf("CHI"));
6154 Info_Number = 0x0018;
6156 Info_Sent_Flag = true;
6157 mixer_set_bchannel_id (plci, Info_Element);
6159 case 19: /* Redirected Number */
6160 dbug(1,dprintf("RDN"));
6161 Info_Number = 0x0074;
6163 Info_Sent_Flag = true;
6165 case 20: /* Redirected Number extended */
6166 dbug(1,dprintf("RDX"));
6167 Info_Number = 0x0073;
6169 Info_Sent_Flag = true;
6171 case 22: /* Redirecing Number */
6172 dbug(1,dprintf("RIN"));
6173 Info_Number = 0x0076;
6175 Info_Sent_Flag = true;
6183 if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6184 Info_Number = 0x8000 |5;
6189 if(Info_Sent_Flag && Info_Number){
6190 if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6191 sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6198 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6205 byte * Info_Element;
6207 static byte charges[5] = {4,0,0,0,0};
6208 static byte cause[] = {0x02,0x80,0x00};
6211 dbug(1,dprintf("InfoParse "));
6216 && plci->Sig.Ind!=NCR_FACILITY
6219 dbug(1,dprintf("NoParse "));
6223 for(i=0; i<MAXPARMSIDS; i++) {
6230 dbug(1,dprintf("CPN "));
6231 Info_Number = 0x0070;
6234 case 7: /* ESC_CAU */
6235 dbug(1,dprintf("cau(0x%x)",ie[2]));
6236 Info_Number = 0x0008;
6239 Info_Element = NULL;
6241 case 8: /* display */
6242 dbug(1,dprintf("display(%d)",i));
6243 Info_Number = 0x0028;
6246 case 9: /* Date display */
6247 dbug(1,dprintf("date(%d)",i));
6248 Info_Number = 0x0029;
6251 case 10: /* charges */
6252 for(j=0;j<4;j++) charges[1+j] = 0;
6253 for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6254 for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6255 Info_Number = 0x4000;
6257 Info_Element = charges;
6259 case 11: /* user user info */
6260 dbug(1,dprintf("uui"));
6261 Info_Number = 0x007E;
6264 case 12: /* congestion receiver ready */
6265 dbug(1,dprintf("clRDY"));
6266 Info_Number = 0x00B0;
6270 case 13: /* congestion receiver not ready */
6271 dbug(1,dprintf("clNRDY"));
6272 Info_Number = 0x00BF;
6276 case 15: /* Keypad Facility */
6277 dbug(1,dprintf("KEY"));
6278 Info_Number = 0x002C;
6281 case 16: /* Channel Id */
6282 dbug(1,dprintf("CHI"));
6283 Info_Number = 0x0018;
6285 mixer_set_bchannel_id (plci, Info_Element);
6287 case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6288 dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6289 if(!cause[2] || cause[2]<0x80) break; /* eg. layer 1 error */
6290 Info_Number = 0x0008;
6292 if(cause[2] != ie[2]) Info_Element = cause;
6294 case 19: /* Redirected Number */
6295 dbug(1,dprintf("RDN"));
6296 Info_Number = 0x0074;
6299 case 22: /* Redirecing Number */
6300 dbug(1,dprintf("RIN"));
6301 Info_Number = 0x0076;
6304 case 23: /* Notification Indicator */
6305 dbug(1,dprintf("NI"));
6306 Info_Number = (word)NI;
6309 case 26: /* Call State */
6310 dbug(1,dprintf("CST"));
6311 Info_Number = (word)CST;
6312 Info_Mask = 0x01; /* do with cause i.e. for now */
6314 case MAXPARMSIDS-2: /* Escape Message Type, must be the last indication */
6315 dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6316 Info_Number = 0x8000 |ie[3];
6317 if(iesent) Info_Mask = 0xffff;
6318 else Info_Mask = 0x10;
6329 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6331 for(j=0; j<max_appl; j++)
6333 appl = &application[j];
6336 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6338 dbug(1,dprintf("NCR_Ind"));
6340 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6344 else if(!plci->appl)
6345 { /* overlap receiving broadcast */
6350 || Info_Number==UUI )
6352 for(j=0; j<max_appl; j++)
6354 if(test_c_ind_mask_bit (plci, j))
6356 dbug(1,dprintf("Ovl_Ind"));
6358 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6362 } /* all other signalling states */
6364 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6366 dbug(1,dprintf("Std_Ind"));
6368 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6374 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6375 dword info_mask, byte setupParse)
6381 byte * Info_Element;
6389 && plci->Sig.Ind!=NCR_FACILITY
6393 dbug(1,dprintf("NoM-IEParse "));
6396 dbug(1,dprintf("M-IEParse "));
6398 for(i=0; i<MAX_MULTI_IE; i++)
6405 dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6406 Info_Number = (word)ie_type;
6407 Info_Mask = (word)info_mask;
6410 if(plci->Sig.Ind==NCR_FACILITY) /* check controller broadcast */
6412 for(j=0; j<max_appl; j++)
6414 appl = &application[j];
6417 && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6420 dbug(1,dprintf("Mlt_NCR_Ind"));
6421 sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6425 else if(!plci->appl && Info_Number)
6426 { /* overlap receiving broadcast */
6427 for(j=0; j<max_appl; j++)
6429 if(test_c_ind_mask_bit (plci, j))
6432 dbug(1,dprintf("Mlt_Ovl_Ind"));
6433 sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6436 } /* all other signalling states */
6438 && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6441 dbug(1,dprintf("Mlt_Std_Ind"));
6442 sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6448 static void SendSSExtInd(APPL * appl, PLCI * plci, dword Id, byte * * parms)
6451 /* Format of multi_ssext_parms[i][]:
6454 2 byte SSEXT_REQ/SSEXT_IND
6462 && plci->Sig.Ind!=NCR_FACILITY
6464 for(i=0;i<MAX_MULTI_IE;i++)
6466 if(parms[i][0]<6) continue;
6467 if(parms[i][2]==SSEXT_REQ) continue;
6471 parms[i][0]=0; /* kill it */
6472 sendf(appl,_MANUFACTURER_I,
6482 parms[i][0]=0; /* kill it */
6483 sendf(plci->appl,_MANUFACTURER_I,
6494 static void nl_ind(PLCI *plci)
6499 DIVA_CAPI_ADAPTER * a;
6505 byte len, ncci_state;
6508 word fax_feature_bits;
6509 byte fax_send_edata_ack;
6510 static byte v120_header_buffer[2 + 3];
6511 static word fax_info[] = {
6512 0, /* T30_SUCCESS */
6513 _FAX_NO_CONNECTION, /* T30_ERR_NO_DIS_RECEIVED */
6514 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_RESPONSE */
6515 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_RESPONSE */
6516 _FAX_PROTOCOL_ERROR, /* T30_ERR_TOO_MANY_REPEATS */
6517 _FAX_PROTOCOL_ERROR, /* T30_ERR_UNEXPECTED_MESSAGE */
6518 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DCN */
6519 _FAX_LOCAL_ABORT, /* T30_ERR_DTC_UNSUPPORTED */
6520 _FAX_TRAINING_ERROR, /* T30_ERR_ALL_RATES_FAILED */
6521 _FAX_TRAINING_ERROR, /* T30_ERR_TOO_MANY_TRAINS */
6522 _FAX_PARAMETER_ERROR, /* T30_ERR_RECEIVE_CORRUPTED */
6523 _FAX_REMOTE_ABORT, /* T30_ERR_UNEXPECTED_DISC */
6524 _FAX_LOCAL_ABORT, /* T30_ERR_APPLICATION_DISC */
6525 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_DIS */
6526 _FAX_LOCAL_ABORT, /* T30_ERR_INCOMPATIBLE_DCS */
6527 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_NO_COMMAND */
6528 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_COMMAND */
6529 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG */
6530 _FAX_PROTOCOL_ERROR, /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG */
6531 _FAX_NO_CONNECTION, /* T30_ERR_NOT_IDENTIFIED */
6532 _FAX_PROTOCOL_ERROR, /* T30_ERR_SUPERVISORY_TIMEOUT */
6533 _FAX_PARAMETER_ERROR, /* T30_ERR_TOO_LONG_SCAN_LINE */
6534 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS */
6535 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR */
6536 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_FTT */
6537 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_EOM */
6538 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCS_AFTER_MPS */
6539 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_MCF */
6540 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_DCN_AFTER_RTN */
6541 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_CFR */
6542 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOP */
6543 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_EOM */
6544 _FAX_PROTOCOL_ERROR, /* T30_ERR_RETRY_NO_MCF_AFTER_MPS */
6545 0x331d, /* T30_ERR_SUB_SEP_UNSUPPORTED */
6546 0x331e, /* T30_ERR_PWD_UNSUPPORTED */
6547 0x331f, /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED */
6548 _FAX_PROTOCOL_ERROR, /* T30_ERR_INVALID_COMMAND_FRAME */
6549 _FAX_PARAMETER_ERROR, /* T30_ERR_UNSUPPORTED_PAGE_CODING */
6550 _FAX_PARAMETER_ERROR, /* T30_ERR_INVALID_PAGE_CODING */
6551 _FAX_REMOTE_REJECT, /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG */
6552 _FAX_LOCAL_ABORT, /* T30_ERR_TIMEOUT_FROM_APPLICATION */
6553 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6554 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_TRAINING_TIMEOUT */
6555 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_UNEXPECTED_V21 */
6556 _FAX_PROTOCOL_ERROR, /* T30_ERR_V34FAX_PRIMARY_CTS_ON */
6557 _FAX_LOCAL_ABORT, /* T30_ERR_V34FAX_TURNAROUND_POLLING */
6558 _FAX_LOCAL_ABORT /* T30_ERR_V34FAX_V8_INCOMPATIBILITY */
6561 byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6564 static word rtp_info[] = {
6565 GOOD, /* RTP_SUCCESS */
6566 0x3600 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE */
6569 static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6571 0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6572 0x00000000, 0x00000000, 0x00000000, 0x00000000
6575 ch = plci->NL.IndCh;
6577 ncci = a->ch_ncci[ch];
6578 Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6579 if(plci->tel) Id|=EXT_CONTROLLER;
6580 APPLptr = plci->appl;
6581 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",
6582 plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6584 /* in the case if no connect_active_Ind was sent to the appl we wait for */
6586 if (plci->nl_remove_id)
6588 plci->NL.RNR = 2; /* discard */
6589 dbug(1,dprintf("NL discard while remove pending"));
6592 if((plci->NL.Ind &0x0f)==N_CONNECT)
6594 if(plci->State==INC_DIS_PENDING
6595 || plci->State==OUTG_DIS_PENDING
6596 || plci->State==IDLE)
6598 plci->NL.RNR = 2; /* discard */
6599 dbug(1,dprintf("discard n_connect"));
6602 if(plci->State < INC_ACT_PENDING)
6604 plci->NL.RNR = 1; /* flow control */
6605 channel_x_off (plci, ch, N_XON_CONNECT_IND);
6610 if(!APPLptr) /* no application or invalid data */
6611 { /* while reloading the DSP */
6612 dbug(1,dprintf("discard1"));
6617 if (((plci->NL.Ind &0x0f) == N_UDATA)
6618 && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6619 || (plci->B2_prot == 7)
6620 || (plci->B3_prot == 7)) )
6622 plci->ncpi_buffer[0] = 0;
6624 ncpi_state = plci->ncpi_state;
6625 if (plci->NL.complete == 1)
6627 byte * data = &plci->NL.RBuffer->P[0];
6629 if ((plci->NL.RBuffer->length >= 12)
6630 &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6631 ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6633 word conn_opt, ncpi_opt = 0x00;
6634 /* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6636 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6637 plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6638 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6639 plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6641 data++; /* indication code */
6642 data += 2; /* timestamp */
6643 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6644 ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6645 data++; /* connected norm */
6646 conn_opt = GET_WORD(data);
6647 data += 2; /* connected options */
6649 PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6651 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6653 ncpi_opt |= MDM_NCPI_ECM_V42;
6655 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6657 ncpi_opt |= MDM_NCPI_ECM_MNP;
6661 ncpi_opt |= MDM_NCPI_TRANSPARENT;
6663 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6665 ncpi_opt |= MDM_NCPI_COMPRESSED;
6667 PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6668 plci->ncpi_buffer[0] = 4;
6670 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6673 if (plci->B3_prot == 7)
6675 if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6676 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6677 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6679 a->ncci_state[ncci] = INC_ACT_PENDING;
6680 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6681 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6685 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6686 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6687 || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6688 || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6696 if(plci->NL.complete == 2)
6698 if (((plci->NL.Ind &0x0f) == N_UDATA)
6699 && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6701 switch(plci->RData[0].P[0])
6704 case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6705 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6706 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6708 case DTMF_UDATA_INDICATION_ANSWER_TONE:
6709 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6710 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6712 case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6713 dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6715 case DTMF_UDATA_INDICATION_DIGITS_SENT:
6716 dtmf_confirmation (Id, plci);
6720 case UDATA_INDICATION_MIXER_TAP_DATA:
6721 capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6722 i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6725 dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6726 dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6731 case UDATA_INDICATION_MIXER_COEFS_SET:
6732 mixer_indication_coefs_set (Id, plci);
6734 case UDATA_INDICATION_XCONNECT_FROM:
6735 mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6737 case UDATA_INDICATION_XCONNECT_TO:
6738 mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6742 case LEC_UDATA_INDICATION_DISABLE_DETECT:
6743 ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6754 if ((plci->RData[0].PLength != 0)
6755 && ((plci->B2_prot == B2_V120_ASYNC)
6756 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6757 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6760 sendf(plci->appl,_DATA_B3_I,Id,0,
6763 (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6771 sendf(plci->appl,_DATA_B3_I,Id,0,
6774 plci->RData[0].PLength,
6783 fax_feature_bits = 0;
6784 if((plci->NL.Ind &0x0f)==N_CONNECT ||
6785 (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6786 (plci->NL.Ind &0x0f)==N_DISC ||
6787 (plci->NL.Ind &0x0f)==N_EDATA ||
6788 (plci->NL.Ind &0x0f)==N_DISC_ACK)
6791 plci->ncpi_buffer[0] = 0;
6792 switch (plci->B3_prot) {
6795 break; /* no network control protocol info - jfr */
6798 for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6799 plci->ncpi_buffer[0] = (byte)(i+3);
6800 plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6801 plci->ncpi_buffer[2] = 0;
6802 plci->ncpi_buffer[3] = 0;
6804 case 4: /*T.30 - FAX*/
6805 case 5: /*T.30 - FAX*/
6806 if(plci->NL.RLength>=sizeof(T30_INFO))
6808 dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6810 PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6811 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6812 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6813 if (plci->B3_prot == 5)
6815 if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6816 i |= 0x8000; /* This is not an ECM connection */
6817 if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6818 i |= 0x4000; /* This is a connection with MMR compression */
6819 if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6820 i |= 0x2000; /* This is a connection with MR compression */
6821 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6822 i |= 0x0004; /* More documents */
6823 if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6824 i |= 0x0002; /* Fax-polling indication */
6826 dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6827 PUT_WORD(&(plci->ncpi_buffer[3]),i);
6828 PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6829 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6830 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6831 plci->ncpi_buffer[len] = 0;
6832 if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6834 plci->ncpi_buffer[len] = 20;
6835 for (i = 0; i < 20; i++)
6836 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6838 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6840 if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6841 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6843 info = _FAX_PROTOCOL_ERROR;
6846 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6847 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6849 i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6850 while (i < plci->NL.RBuffer->length)
6851 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6854 plci->ncpi_buffer[0] = len;
6855 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6856 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6858 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6859 if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6860 || (((plci->NL.Ind &0x0f) == N_CONNECT)
6861 && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6862 || (((plci->NL.Ind &0x0f) == N_EDATA)
6863 && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6864 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6865 || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6867 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6869 if (((plci->NL.Ind &0x0f) == N_DISC)
6870 || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6871 || (((plci->NL.Ind &0x0f) == N_EDATA)
6872 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6874 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6880 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6882 if (plci->NL.RLength != 0)
6884 info = rtp_info[plci->NL.RBuffer->P[0]];
6885 plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6886 for (i = 1; i < plci->NL.RLength; i++)
6887 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6895 switch(plci->NL.Ind &0x0f) {
6897 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6899 dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6900 ((T30_INFO *)plci->NL.RBuffer->P)->code));
6901 fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6903 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6904 && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6905 && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6906 && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6907 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6908 && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6910 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6911 sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6912 (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6913 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6914 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6915 fax_send_edata_ack = false;
6918 if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6920 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6923 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6924 && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6925 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6926 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6928 a->ncci_state[ncci] = INC_ACT_PENDING;
6929 if (plci->B3_prot == 4)
6930 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6932 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6933 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6937 case EDATA_T30_TRAIN_OK:
6938 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6939 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6940 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6942 if (plci->B3_prot == 4)
6943 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6945 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6946 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6950 case EDATA_T30_EOP_CAPI:
6951 if (a->ncci_state[ncci] == CONNECTED)
6953 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6954 a->ncci_state[ncci] = INC_DIS_PENDING;
6955 plci->ncpi_state = 0;
6956 fax_send_edata_ack = false;
6963 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6965 case EDATA_T30_TRAIN_OK:
6966 if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6967 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6968 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6970 if (plci->B3_prot == 4)
6971 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6973 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6974 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6979 if (fax_send_edata_ack)
6981 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6982 plci->fax_edata_ack_length = 1;
6983 start_internal_command (Id, plci, fax_edata_ack_command);
6988 dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6992 if (!a->ch_ncci[ch])
6994 ncci = get_ncci (plci, ch, 0);
6995 Id = (Id & 0xffff) | (((dword) ncci) << 16);
6997 dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6998 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
7000 msg = _CONNECT_B3_I;
7001 if (a->ncci_state[ncci] == IDLE)
7003 else if (plci->B3_prot == 1)
7004 msg = _CONNECT_B3_T90_ACTIVE_I;
7006 a->ncci_state[ncci] = INC_CON_PENDING;
7007 if(plci->B3_prot == 4)
7008 sendf(plci->appl,msg,Id,0,"s","");
7010 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7013 dbug(1,dprintf("N_connect_Ack"));
7014 if (plci->internal_command_queue[0]
7015 && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7016 || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7017 || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7019 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7020 if (!plci->internal_command)
7021 next_internal_command (Id, plci);
7024 msg = _CONNECT_B3_ACTIVE_I;
7025 if (plci->B3_prot == 1)
7027 if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7028 msg = _CONNECT_B3_T90_ACTIVE_I;
7029 a->ncci_state[ncci] = INC_ACT_PENDING;
7030 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7032 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7034 if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7035 && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7036 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7038 a->ncci_state[ncci] = INC_ACT_PENDING;
7039 if (plci->B3_prot == 4)
7040 sendf(plci->appl,msg,Id,0,"s","");
7042 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7043 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7048 a->ncci_state[ncci] = INC_ACT_PENDING;
7049 sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7051 if (plci->adjust_b_restore)
7053 plci->adjust_b_restore = false;
7054 start_internal_command (Id, plci, adjust_b_restore);
7059 if (plci->internal_command_queue[0]
7060 && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7061 || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7062 || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7064 (*(plci->internal_command_queue[0]))(Id, plci, 0);
7065 if (!plci->internal_command)
7066 next_internal_command (Id, plci);
7068 ncci_state = a->ncci_state[ncci];
7069 ncci_remove (plci, ncci, false);
7071 /* with N_DISC or N_DISC_ACK the IDI frees the respective */
7072 /* channel, so we cannot store the state in ncci_state! The */
7073 /* information which channel we received a N_DISC is thus */
7074 /* stored in the inc_dis_ncci_table buffer. */
7075 for(i=0; plci->inc_dis_ncci_table[i]; i++);
7076 plci->inc_dis_ncci_table[i] = (byte) ncci;
7078 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7080 && (plci->B1_resource == 16)
7081 && (plci->State <= CONNECTED))
7084 i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7085 PUT_WORD (&plci->ncpi_buffer[1], i);
7086 PUT_WORD (&plci->ncpi_buffer[3], 0);
7087 i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7088 PUT_WORD (&plci->ncpi_buffer[5], i);
7089 PUT_WORD (&plci->ncpi_buffer[7], 0);
7090 plci->ncpi_buffer[len] = 0;
7091 plci->ncpi_buffer[0] = len;
7092 if(plci->B3_prot == 4)
7093 sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7097 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7098 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7100 plci->ncpi_buffer[++len] = 0;
7101 plci->ncpi_buffer[++len] = 0;
7102 plci->ncpi_buffer[++len] = 0;
7103 plci->ncpi_buffer[0] = len;
7106 sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7108 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7109 plci->ncpi_state = 0;
7110 sig_req(plci,HANGUP,0);
7112 plci->State = OUTG_DIS_PENDING;
7115 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7116 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7117 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7119 if (ncci_state == IDLE)
7123 if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7124 if(plci->State == SUSPENDING){
7129 "ws", (word)3, "\x03\x04\x00\x00");
7130 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7137 else if (plci->channels)
7139 sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7140 plci->ncpi_state = 0;
7141 if ((ncci_state == OUTG_REJ_PENDING)
7142 && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7144 sig_req(plci,HANGUP,0);
7146 plci->State = OUTG_DIS_PENDING;
7151 a->ncci_state[ncci] = INC_RES_PENDING;
7152 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7155 a->ncci_state[ncci] = CONNECTED;
7156 sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7160 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7162 plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7163 plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7164 plci->NL.R = plci->RData;
7170 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7171 || (a->ncci_state[ncci] == IDLE)
7172 || (a->ncci_state[ncci] == INC_DIS_PENDING))
7177 if ((a->ncci_state[ncci] != CONNECTED)
7178 && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7179 && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7181 dbug(1,dprintf("flow control"));
7182 plci->NL.RNR = 1; /* flow control */
7183 channel_x_off (plci, ch, 0);
7187 NCCIcode = ncci | (((word)a->Id) << 8);
7189 /* count all buffers within the Application pool */
7190 /* belonging to the same NCCI. If this is below the */
7191 /* number of buffers available per NCCI we accept */
7192 /* this packet, otherwise we reject it */
7195 for(i=0; i<APPLptr->MaxBuffer; i++) {
7196 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7197 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7200 if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7202 dbug(3,dprintf("Flow-Control"));
7204 if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7205 (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7208 dbug(3,dprintf("DiscardData"));
7210 channel_x_off (plci, ch, 0);
7216 APPLptr->NCCIDataFlowCtrlTimer = 0;
7219 plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7220 if(!plci->RData[0].P) {
7222 channel_x_off (plci, ch, 0);
7226 APPLptr->DataNCCI[Num] = NCCIcode;
7227 APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7228 dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7231 plci->RFlags = plci->NL.Ind>>4;
7232 plci->RData[0].PLength = APPLptr->MaxDataLength;
7233 plci->NL.R = plci->RData;
7234 if ((plci->NL.RLength != 0)
7235 && ((plci->B2_prot == B2_V120_ASYNC)
7236 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7237 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7239 plci->RData[1].P = plci->RData[0].P;
7240 plci->RData[1].PLength = plci->RData[0].PLength;
7241 plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7242 if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7243 plci->RData[0].PLength = 1;
7245 plci->RData[0].PLength = 2;
7246 if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7247 plci->RFlags |= 0x0010;
7248 if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7249 plci->RFlags |= 0x8000;
7254 if((plci->NL.Ind &0x0f)==N_UDATA)
7255 plci->RFlags |= 0x0010;
7257 else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7258 plci->RFlags |= 0x0001;
7264 data_ack (plci, ch);
7272 /*------------------------------------------------------------------*/
7273 /* find a free PLCI */
7274 /*------------------------------------------------------------------*/
7276 static word get_plci(DIVA_CAPI_ADAPTER *a)
7282 for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7283 if(i==a->max_plci) {
7284 dbug(1,dprintf("get_plci: out of PLCIs"));
7288 plci->Id = (byte)(i+1);
7296 plci->relatedPTYPLCI = NULL;
7298 plci->SuppState = IDLE;
7301 plci->B1_resource = 0;
7306 plci->m_command = 0;
7307 init_internal_command_queue (plci);
7309 plci->req_in_start = 0;
7312 plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7313 plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7314 plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7316 plci->data_sent = false;
7317 plci->send_disc = 0;
7318 plci->sig_global_req = 0;
7319 plci->sig_remove_id = 0;
7320 plci->nl_global_req = 0;
7321 plci->nl_remove_id = 0;
7323 plci->manufacturer = false;
7324 plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7325 plci->spoofed_msg = 0;
7327 plci->cr_enquiry = false;
7328 plci->hangup_flow_ctrl_timer = 0;
7330 plci->ncci_ring_list = 0;
7331 for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7332 clear_c_ind_mask (plci);
7333 set_group_ind_mask (plci);
7334 plci->fax_connect_info_length = 0;
7335 plci->nsf_control_bits = 0;
7336 plci->ncpi_state = 0x00;
7337 plci->ncpi_buffer[0] = 0;
7339 plci->requested_options_conn = 0;
7340 plci->requested_options = 0;
7341 plci->notifiedcall = 0;
7342 plci->vswitchstate = 0;
7344 plci->vsprotdialect = 0;
7345 init_b1_config (plci);
7346 dbug(1,dprintf("get_plci(%x)",plci->Id));
7350 /*------------------------------------------------------------------*/
7351 /* put a parameter in the parameter buffer */
7352 /*------------------------------------------------------------------*/
7354 static void add_p(PLCI * plci, byte code, byte * p)
7359 if(p) p_length = p[0];
7360 add_ie(plci, code, p, p_length);
7363 /*------------------------------------------------------------------*/
7364 /* put a structure in the parameter buffer */
7365 /*------------------------------------------------------------------*/
7366 static void add_s(PLCI * plci, byte code, API_PARSE * p)
7368 if(p) add_ie(plci, code, p->info, (word)p->length);
7371 /*------------------------------------------------------------------*/
7372 /* put multiple structures in the parameter buffer */
7373 /*------------------------------------------------------------------*/
7374 static void add_ss(PLCI * plci, byte code, API_PARSE * p)
7379 dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7380 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7381 dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7382 add_ie(plci, p->info[i-1], (byte *)&(p->info[i]), (word)p->info[i]);
7387 /*------------------------------------------------------------------*/
7388 /* return the channel number sent by the application in a esc_chi */
7389 /*------------------------------------------------------------------*/
7390 static byte getChannel(API_PARSE * p)
7395 for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7397 if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7405 /*------------------------------------------------------------------*/
7406 /* put an information element in the parameter buffer */
7407 /*------------------------------------------------------------------*/
7409 static void add_ie(PLCI * plci, byte code, byte * p, word p_length)
7413 if(!(code &0x80) && !p_length) return;
7415 if(plci->req_in==plci->req_in_start) {
7421 plci->RBuffer[plci->req_in++] = code;
7424 plci->RBuffer[plci->req_in++] = (byte)p_length;
7425 for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7428 plci->RBuffer[plci->req_in++] = 0;
7431 /*------------------------------------------------------------------*/
7432 /* put a unstructured data into the buffer */
7433 /*------------------------------------------------------------------*/
7435 static void add_d(PLCI *plci, word length, byte *p)
7439 if(plci->req_in==plci->req_in_start) {
7445 for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7448 /*------------------------------------------------------------------*/
7449 /* put parameters from the Additional Info parameter in the */
7450 /* parameter buffer */
7451 /*------------------------------------------------------------------*/
7453 static void add_ai(PLCI *plci, API_PARSE *ai)
7456 API_PARSE ai_parms[5];
7458 for(i=0;i<5;i++) ai_parms[i].length = 0;
7462 if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7465 add_s (plci,KEY,&ai_parms[1]);
7466 add_s (plci,UUI,&ai_parms[2]);
7467 add_ss(plci,FTY,&ai_parms[3]);
7470 /*------------------------------------------------------------------*/
7471 /* put parameter for b1 protocol in the parameter buffer */
7472 /*------------------------------------------------------------------*/
7474 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7477 API_PARSE bp_parms[8];
7478 API_PARSE mdm_cfg[9];
7479 API_PARSE global_config[2];
7481 byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7482 byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7485 API_PARSE mdm_cfg_v18[4];
7490 for(i=0;i<8;i++) bp_parms[i].length = 0;
7491 for(i=0;i<2;i++) global_config[i].length = 0;
7493 dbug(1,dprintf("add_b1"));
7494 api_save_msg(bp, "s", &plci->B_protocol);
7496 if(b_channel_info==2){
7497 plci->B1_resource = 0;
7498 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7499 add_p(plci, CAI, "\x01\x00");
7500 dbug(1,dprintf("Cai=1,0 (no resource)"));
7504 if(plci->tel == CODEC_PERMANENT) return 0;
7505 else if(plci->tel == CODEC){
7506 plci->B1_resource = 1;
7507 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7508 add_p(plci, CAI, "\x01\x01");
7509 dbug(1,dprintf("Cai=1,1 (Codec)"));
7512 else if(plci->tel == ADV_VOICE){
7513 plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7514 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7515 voice_cai[1] = plci->B1_resource;
7516 PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7517 add_p(plci, CAI, voice_cai);
7518 dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7521 plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7522 if (plci->call_dir & CALL_DIR_OUT)
7523 plci->call_dir |= CALL_DIR_ORIGINATE;
7524 else if (plci->call_dir & CALL_DIR_IN)
7525 plci->call_dir |= CALL_DIR_ANSWER;
7528 plci->B1_resource = 0x5;
7529 adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7530 add_p(plci, CAI, "\x01\x05");
7534 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7535 if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7536 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7538 bp_parms[6].length = 0;
7539 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7541 dbug(1,dprintf("b-form.!"));
7542 return _WRONG_MESSAGE_FORMAT;
7545 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7547 dbug(1,dprintf("b-form.!"));
7548 return _WRONG_MESSAGE_FORMAT;
7551 if(bp_parms[6].length)
7553 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7555 return _WRONG_MESSAGE_FORMAT;
7557 switch(GET_WORD(global_config[0].info))
7560 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7563 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7567 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7570 if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7571 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7573 plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7574 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7575 cai[1] = plci->B1_resource;
7579 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7580 for (i = 0; i < bp_parms[3].length; i++)
7581 cai[7+i] = bp_parms[3].info[1+i];
7582 cai[0] = 6 + bp_parms[3].length;
7583 add_p(plci, CAI, cai);
7588 if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7589 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7591 plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7592 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7593 cai[1] = plci->B1_resource;
7597 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7599 add_p(plci, CAI, cai);
7604 if ((GET_WORD(bp_parms[0].info) >= 32)
7605 || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7606 && ((GET_WORD(bp_parms[0].info) != 3)
7607 || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7608 || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7610 return _B1_NOT_SUPPORTED;
7612 plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7613 (word)(b1_facilities & ~B1_FACILITY_VOICE));
7614 adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7616 cai[1] = plci->B1_resource;
7617 for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7619 if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7620 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7621 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7623 for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7625 if (bp_parms[3].length)
7627 if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7629 return (_WRONG_MESSAGE_FORMAT);
7632 cai[2] = 0; /* Bit rate for adaptation */
7634 dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7636 PUT_WORD (&cai[13], 0); /* Min Tx speed */
7637 PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7638 PUT_WORD (&cai[17], 0); /* Min Rx speed */
7639 PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7641 cai[3] = 0; /* Async framing parameters */
7642 switch (GET_WORD (mdm_cfg[2].info))
7644 case 1: /* odd parity */
7645 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7646 dbug(1,dprintf("MDM: odd parity"));
7649 case 2: /* even parity */
7650 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7651 dbug(1,dprintf("MDM: even parity"));
7655 dbug(1,dprintf("MDM: no parity"));
7659 switch (GET_WORD (mdm_cfg[3].info))
7661 case 1: /* 2 stop bits */
7662 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7663 dbug(1,dprintf("MDM: 2 stop bits"));
7667 dbug(1,dprintf("MDM: 1 stop bit"));
7671 switch (GET_WORD (mdm_cfg[1].info))
7674 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7675 dbug(1,dprintf("MDM: 5 bits"));
7679 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7680 dbug(1,dprintf("MDM: 6 bits"));
7684 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7685 dbug(1,dprintf("MDM: 7 bits"));
7689 dbug(1,dprintf("MDM: 8 bits"));
7693 cai[7] = 0; /* Line taking options */
7694 cai[8] = 0; /* Modulation negotiation options */
7695 cai[9] = 0; /* Modulation options */
7697 if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7699 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7700 dbug(1, dprintf("MDM: Reverse direction"));
7703 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7705 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7706 dbug(1, dprintf("MDM: Disable retrain"));
7709 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7711 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7712 dbug(1, dprintf("MDM: Disable ring tone"));
7715 if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7717 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7718 dbug(1, dprintf("MDM: 1800 guard tone"));
7720 else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7722 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7723 dbug(1, dprintf("MDM: 550 guard tone"));
7726 if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7728 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7729 dbug(1, dprintf("MDM: V100"));
7731 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7733 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7734 dbug(1, dprintf("MDM: IN CLASS"));
7736 else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7738 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7739 dbug(1, dprintf("MDM: DISABLED"));
7743 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7744 && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7746 plci->requested_options |= 1L << PRIVATE_V18;
7748 if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7749 plci->requested_options |= 1L << PRIVATE_VOWN;
7751 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7752 & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7754 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7757 if (mdm_cfg[6].length >= 4)
7759 d = GET_DWORD(&mdm_cfg[6].info[1]);
7760 cai[7] |= (byte) d; /* line taking options */
7761 cai[9] |= (byte)(d >> 8); /* modulation options */
7762 cai[++i] = (byte)(d >> 16); /* vown modulation options */
7763 cai[++i] = (byte)(d >> 24);
7764 if (mdm_cfg[6].length >= 8)
7766 d = GET_DWORD(&mdm_cfg[6].info[5]);
7767 cai[10] |= (byte) d; /* disabled modulations mask */
7768 cai[11] |= (byte)(d >> 8);
7769 if (mdm_cfg[6].length >= 12)
7771 d = GET_DWORD(&mdm_cfg[6].info[9]);
7772 cai[12] = (byte) d; /* enabled modulations mask */
7773 cai[++i] = (byte)(d >> 8); /* vown enabled modulations */
7774 cai[++i] = (byte)(d >> 16);
7775 cai[++i] = (byte)(d >> 24);
7777 if (mdm_cfg[6].length >= 14)
7779 w = GET_WORD(&mdm_cfg[6].info[13]);
7781 PUT_WORD(&cai[13], w); /* min tx speed */
7782 if (mdm_cfg[6].length >= 16)
7784 w = GET_WORD(&mdm_cfg[6].info[15]);
7786 PUT_WORD(&cai[15], w); /* max tx speed */
7787 if (mdm_cfg[6].length >= 18)
7789 w = GET_WORD(&mdm_cfg[6].info[17]);
7791 PUT_WORD(&cai[17], w); /* min rx speed */
7792 if (mdm_cfg[6].length >= 20)
7794 w = GET_WORD(&mdm_cfg[6].info[19]);
7796 PUT_WORD(&cai[19], w); /* max rx speed */
7797 if (mdm_cfg[6].length >= 22)
7799 w = GET_WORD(&mdm_cfg[6].info[21]);
7800 cai[23] = (byte)(-((short) w)); /* transmit level */
7801 if (mdm_cfg[6].length >= 24)
7803 w = GET_WORD(&mdm_cfg[6].info[23]);
7804 cai[22] |= (byte) w; /* info options mask */
7805 cai[21] |= (byte)(w >> 8); /* disabled symbol rates */
7817 if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7819 if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7821 for (n = 0; n < 3; n++)
7823 cai[i] = (byte)(mdm_cfg_v18[n].length);
7824 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7825 cai[i+j] = mdm_cfg_v18[n].info[j];
7830 cai[0] = (byte)(i - 1);
7836 if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */
7837 GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */
7839 if(bp_parms[3].length){
7840 dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7841 switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */
7844 if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */
7845 dbug(1,dprintf("56k sync HSCX"));
7850 else if(GET_WORD(bp_parms[0].info)==2){
7851 dbug(1,dprintf("56k async DSP"));
7855 case 50: cai[2] = 1; break;
7856 case 75: cai[2] = 1; break;
7857 case 110: cai[2] = 1; break;
7858 case 150: cai[2] = 1; break;
7859 case 200: cai[2] = 1; break;
7860 case 300: cai[2] = 1; break;
7861 case 600: cai[2] = 1; break;
7862 case 1200: cai[2] = 2; break;
7863 case 2400: cai[2] = 3; break;
7864 case 4800: cai[2] = 4; break;
7865 case 7200: cai[2] = 10; break;
7866 case 9600: cai[2] = 5; break;
7867 case 12000: cai[2] = 13; break;
7868 case 24000: cai[2] = 0; break;
7869 case 14400: cai[2] = 11; break;
7870 case 19200: cai[2] = 6; break;
7871 case 28800: cai[2] = 12; break;
7872 case 38400: cai[2] = 7; break;
7873 case 48000: cai[2] = 8; break;
7874 case 76: cai[2] = 15; break; /* 75/1200 */
7875 case 1201: cai[2] = 14; break; /* 1200/75 */
7876 case 56001: cai[2] = 9; break; /* V.110 56000 */
7879 return _B1_PARM_NOT_SUPPORTED;
7882 if (cai[1] == 13) /* v.110 async */
7884 if (bp_parms[3].length >= 8)
7886 switch (GET_WORD (&bp_parms[3].info[3]))
7889 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7892 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7895 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7898 switch (GET_WORD (&bp_parms[3].info[5]))
7900 case 1: /* odd parity */
7901 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7903 case 2: /* even parity */
7904 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7907 switch (GET_WORD (&bp_parms[3].info[7]))
7909 case 1: /* 2 stop bits */
7910 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7916 else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7917 dbug(1,dprintf("V.110 default 56k sync"));
7923 dbug(1,dprintf("V.110 default 9600 async"));
7927 PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7928 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]));
7929 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7931 add_p(plci, CAI, cai);
7935 /*------------------------------------------------------------------*/
7936 /* put parameter for b2 and B3 protocol in the parameter buffer */
7937 /*------------------------------------------------------------------*/
7939 static word add_b23(PLCI *plci, API_PARSE *bp)
7941 word i, fax_control_bits;
7943 byte SAPI = 0x40; /* default SAPI 16 for x.31 */
7944 API_PARSE bp_parms[8];
7945 API_PARSE * b1_config;
7946 API_PARSE * b2_config;
7947 API_PARSE b2_config_parms[8];
7948 API_PARSE * b3_config;
7949 API_PARSE b3_config_parms[6];
7950 API_PARSE global_config[2];
7952 static byte llc[3] = {2,0,0};
7953 static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7954 static byte nlc[256];
7955 static byte lli[12] = {1,1};
7957 const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7958 const byte llc2_in[] = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7960 const byte llc3[] = {4,3,2,2,6,6,0};
7961 const byte header[] = {0,2,3,3,0,0,0};
7963 for(i=0;i<8;i++) bp_parms[i].length = 0;
7964 for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7965 for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7969 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7971 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7974 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7976 if (plci->rx_dma_descriptor <= 0) {
7977 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7978 if (plci->rx_dma_descriptor >= 0)
7979 plci->rx_dma_descriptor++;
7981 if (plci->rx_dma_descriptor > 0) {
7984 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7985 lli[3] = (byte)plci->rx_dma_magic;
7986 lli[4] = (byte)(plci->rx_dma_magic >> 8);
7987 lli[5] = (byte)(plci->rx_dma_magic >> 16);
7988 lli[6] = (byte)(plci->rx_dma_magic >> 24);
7992 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7996 dbug(1,dprintf("add_b23"));
7997 api_save_msg(bp, "s", &plci->B_protocol);
7999 if(!bp->length && plci->tel)
8001 plci->adv_nl = true;
8002 dbug(1,dprintf("Default adv.Nl"));
8003 add_p(plci,LLI,lli);
8004 plci->B2_prot = 1 /*XPARENT*/;
8005 plci->B3_prot = 0 /*XPARENT*/;
8008 add_p(plci, LLC, llc);
8010 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8011 add_p(plci, DLC, dlc);
8015 if(!bp->length) /*default*/
8017 dbug(1,dprintf("ret default"));
8018 add_p(plci,LLI,lli);
8019 plci->B2_prot = 0 /*X.75 */;
8020 plci->B3_prot = 0 /*XPARENT*/;
8023 add_p(plci, LLC, llc);
8025 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8026 add_p(plci, DLC, dlc);
8029 dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8030 if((word)bp->length > 256) return _WRONG_MESSAGE_FORMAT;
8032 if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8034 bp_parms[6].length = 0;
8035 if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8037 dbug(1,dprintf("b-form.!"));
8038 return _WRONG_MESSAGE_FORMAT;
8041 else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8043 dbug(1,dprintf("b-form.!"));
8044 return _WRONG_MESSAGE_FORMAT;
8047 if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8049 if(GET_WORD(bp_parms[1].info)!=1
8050 || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8051 plci->adv_nl = true;
8053 else if(plci->tel) return _B2_NOT_SUPPORTED;
8056 if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8057 && (GET_WORD(bp_parms[2].info) == B3_RTP)
8058 && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8060 add_p(plci,LLI,lli);
8061 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8062 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8063 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8065 add_p(plci, LLC, llc);
8067 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8068 dlc[3] = 3; /* Addr A */
8069 dlc[4] = 1; /* Addr B */
8070 dlc[5] = 7; /* modulo mode */
8071 dlc[6] = 7; /* window size */
8072 dlc[7] = 0; /* XID len Lo */
8073 dlc[8] = 0; /* XID len Hi */
8074 for (i = 0; i < bp_parms[4].length; i++)
8075 dlc[9+i] = bp_parms[4].info[1+i];
8076 dlc[0] = (byte)(8 + bp_parms[4].length);
8077 add_p(plci, DLC, dlc);
8078 for (i = 0; i < bp_parms[5].length; i++)
8079 nlc[1+i] = bp_parms[5].info[1+i];
8080 nlc[0] = (byte)(bp_parms[5].length);
8081 add_p(plci, NLC, nlc);
8087 if ((GET_WORD(bp_parms[1].info) >= 32)
8088 || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8089 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8090 || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8093 return _B2_NOT_SUPPORTED;
8095 if ((GET_WORD(bp_parms[2].info) >= 32)
8096 || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8098 return _B3_NOT_SUPPORTED;
8100 if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8101 && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8102 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8103 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8105 return (add_modem_b23 (plci, bp_parms));
8108 add_p(plci,LLI,lli);
8110 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8111 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8112 if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8114 if(bp_parms[6].length)
8116 if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8118 return _WRONG_MESSAGE_FORMAT;
8120 switch(GET_WORD(global_config[0].info))
8123 plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8126 plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8130 dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8133 if (plci->B2_prot == B2_PIAFS)
8136 /* IMPLEMENT_PIAFS */
8138 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8139 llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8141 llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8143 add_p(plci, LLC, llc);
8146 PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8147 header[GET_WORD(bp_parms[2].info)]);
8149 b1_config = &bp_parms[3];
8151 if(plci->B3_prot == 4
8152 || plci->B3_prot == 5)
8154 for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8155 nlc[0] = sizeof(T30_INFO);
8156 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8157 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8158 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8159 if(b1_config->length>=2)
8161 ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8164 b2_config = &bp_parms[4];
8167 if (llc[1] == PIAFS_CRC)
8169 if (plci->B3_prot != B3_TRANSPARENT)
8171 return _B_STACK_NOT_SUPPORTED;
8173 if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8174 return _WRONG_MESSAGE_FORMAT;
8176 PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8177 dlc[3] = 0; /* Addr A */
8178 dlc[4] = 0; /* Addr B */
8179 dlc[5] = 0; /* modulo mode */
8180 dlc[6] = 0; /* window size */
8181 if (b2_config->length >= 7){
8184 dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8185 dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8186 dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8187 dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8188 dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8189 dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8190 dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8192 if(b2_config->length >= 8) { /* PIAFS control abilities */
8194 dlc[16] = 2; /* Length of PIAFS extention */
8195 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8196 dlc[18] = b2_config_parms[4].info[0]; /* value */
8200 else /* default values, 64K, variable, no compression */
8204 dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8205 dlc[10] = 0x03; /* V.42bis P0 */
8206 dlc[11] = 0; /* V.42bis P0 */
8207 dlc[12] = 0; /* V.42bis P1 */
8208 dlc[13] = 0; /* V.42bis P1 */
8209 dlc[14] = 0; /* V.42bis P2 */
8210 dlc[15] = 0; /* V.42bis P2 */
8213 add_p(plci, DLC, dlc);
8217 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8219 if (plci->B3_prot != B3_TRANSPARENT)
8220 return _B_STACK_NOT_SUPPORTED;
8223 PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8228 if (b2_config->length != 0)
8230 if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8231 return _WRONG_MESSAGE_FORMAT;
8233 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8234 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8235 if (b2_config->info[3] != 128)
8237 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8238 return _B2_PARM_NOT_SUPPORTED;
8240 dlc[5] = (byte)(b2_config->info[3] - 1);
8241 dlc[6] = b2_config->info[4];
8242 if(llc[1]==V120_V42BIS){
8243 if (b2_config->length >= 10){
8246 dlc[ 9] = b2_config_parms[4].info[0];
8247 dlc[10] = b2_config_parms[4].info[1];
8248 dlc[11] = b2_config_parms[5].info[0];
8249 dlc[12] = b2_config_parms[5].info[1];
8250 dlc[13] = b2_config_parms[6].info[0];
8251 dlc[14] = b2_config_parms[6].info[1];
8253 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8254 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8255 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8265 if(b2_config->length)
8267 dbug(1,dprintf("B2-Config"));
8268 if(llc[1]==X75_V42BIS){
8269 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8271 return _WRONG_MESSAGE_FORMAT;
8275 if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8277 return _WRONG_MESSAGE_FORMAT;
8280 /* if B2 Protocol is LAPD, b2_config structure is different */
8284 if(b2_config->length>=1) dlc[2] = b2_config->info[1]; /* TEI */
8286 if( (b2_config->length>=2) && (plci->B2_prot==12) )
8288 SAPI = b2_config->info[2]; /* SAPI */
8291 if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8293 dlc[3] = 127; /* Mode */
8297 dlc[3] = 7; /* Mode */
8300 if(b2_config->length>=4) dlc[4] = b2_config->info[4]; /* Window */
8302 dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8303 if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8307 dlc[0] = (byte)(b2_config_parms[4].length+6);
8308 dlc[3] = b2_config->info[1];
8309 dlc[4] = b2_config->info[2];
8310 if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8311 dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8312 return _B2_PARM_NOT_SUPPORTED;
8315 dlc[5] = (byte)(b2_config->info[3]-1);
8316 dlc[6] = b2_config->info[4];
8318 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]));
8319 return _B2_PARM_NOT_SUPPORTED;
8322 if(llc[1]==X75_V42BIS) {
8323 if (b2_config->length >= 10){
8326 dlc[ 9] = b2_config_parms[4].info[0];
8327 dlc[10] = b2_config_parms[4].info[1];
8328 dlc[11] = b2_config_parms[5].info[0];
8329 dlc[12] = b2_config_parms[5].info[1];
8330 dlc[13] = b2_config_parms[6].info[0];
8331 dlc[14] = b2_config_parms[6].info[1];
8333 dbug(1,dprintf("b2_config_parms[4].info[0] [1]: %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8334 dbug(1,dprintf("b2_config_parms[5].info[0] [1]: %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8335 dbug(1,dprintf("b2_config_parms[6].info[0] [1]: %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8343 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8344 for(i=0; i<b2_config_parms[4].length; i++)
8345 dlc[11+i] = b2_config_parms[4].info[1+i];
8350 add_p(plci, DLC, dlc);
8352 b3_config = &bp_parms[5];
8353 if(b3_config->length)
8355 if(plci->B3_prot == 4
8356 || plci->B3_prot == 5)
8358 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8360 return _WRONG_MESSAGE_FORMAT;
8362 i = GET_WORD((byte *)(b3_config_parms[0].info));
8363 ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8364 ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8365 ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8366 fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8367 if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8368 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8369 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8372 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8373 & (1L << PRIVATE_FAX_PAPER_FORMATS))
8375 ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8376 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8377 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8380 ((T30_INFO *)&nlc[1])->recording_properties =
8381 T30_RECORDING_WIDTH_ISO_A3 |
8382 (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8383 (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8385 if(plci->B3_prot == 5)
8387 if (i & 0x0002) /* Accept incoming fax-polling requests */
8388 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8389 if (i & 0x2000) /* Do not use MR compression */
8390 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8391 if (i & 0x4000) /* Do not use MMR compression */
8392 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8393 if (i & 0x8000) /* Do not use ECM */
8394 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8395 if (plci->fax_connect_info_length != 0)
8397 ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8398 ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8399 ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8400 fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8401 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8404 /* copy station id to NLC */
8407 if(i<b3_config_parms[2].length)
8409 ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1+i];
8413 ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8416 ((T30_INFO *)&nlc[1])->station_id_len = 20;
8417 /* copy head line to NLC */
8418 if(b3_config_parms[3].length)
8421 pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8424 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8428 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8429 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8430 len = (byte)b3_config_parms[2].length;
8433 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8435 for (i = 0; i < len; i++)
8436 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i];
8437 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8438 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8443 len = (byte)b3_config_parms[3].length;
8444 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8445 len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8446 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8447 nlc[0] += (byte)(pos + len);
8448 for (i = 0; i < len; i++)
8449 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i];
8452 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8454 plci->nsf_control_bits = 0;
8455 if(plci->B3_prot == 5)
8457 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8458 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8460 plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8462 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8463 && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8465 plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8467 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468 & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8470 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8471 & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8473 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8474 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8475 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8478 pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8479 if (pos < plci->fax_connect_info_length)
8481 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8482 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8486 if (pos < plci->fax_connect_info_length)
8488 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8489 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8493 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8494 & (1L << PRIVATE_FAX_NONSTANDARD))
8496 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8498 if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8499 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8500 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8501 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8505 if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8507 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8512 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8513 plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8514 nlc[++len] = (byte)(b3_config_parms[4].length);
8515 for (i = 0; i < b3_config_parms[4].length; i++)
8516 nlc[++len] = b3_config_parms[4].info[1+i];
8521 if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8522 && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8524 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8529 PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8530 len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8531 for (i = 0; i < len; i++)
8532 plci->fax_connect_info_buffer[i] = nlc[1+i];
8533 ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8534 i += ((T30_INFO *)&nlc[1])->head_line_len;
8536 plci->fax_connect_info_buffer[len++] = nlc[++i];
8537 plci->fax_connect_info_length = len;
8542 if(b3_config->length!=16)
8543 return _B3_PARM_NOT_SUPPORTED;
8544 for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8545 if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8546 return _B3_PARM_NOT_SUPPORTED;
8547 nlc[13] = b3_config->info[13];
8548 if(GET_WORD(&b3_config->info[15])>=nlc[13])
8549 return _B3_PARM_NOT_SUPPORTED;
8550 nlc[14] = b3_config->info[15];
8555 if (plci->B3_prot == 4
8556 || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8558 add_p(plci, NLC, nlc);
8562 /*----------------------------------------------------------------*/
8563 /* make the same as add_b23, but only for the modem related */
8564 /* L2 and L3 B-Chan protocol. */
8566 /* Enabled L2 and L3 Configurations: */
8567 /* If L1 == Modem all negotiation */
8568 /* only L2 == Modem with full negotiation is allowed */
8569 /* If L1 == Modem async or sync */
8570 /* only L2 == Transparent is allowed */
8571 /* L3 == Modem or L3 == Transparent are allowed */
8572 /* B2 Configuration for modem: */
8573 /* word : enable/disable compression, bitoptions */
8574 /* B3 Configuration for modem: */
8576 /*----------------------------------------------------------------*/
8577 static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms)
8579 static byte lli[12] = {1,1};
8580 static byte llc[3] = {2,0,0};
8581 static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8582 API_PARSE mdm_config[2];
8586 for(i=0;i<2;i++) mdm_config[i].length = 0;
8587 for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8589 if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8590 && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8591 || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8592 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8594 return (_B_STACK_NOT_SUPPORTED);
8596 if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8597 && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8599 return (_B_STACK_NOT_SUPPORTED);
8602 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8603 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8605 if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8607 if (api_parse (&bp_parms[4].info[1],
8608 (word)bp_parms[4].length, "w",
8611 return (_WRONG_MESSAGE_FORMAT);
8613 b2_config = GET_WORD(mdm_config[0].info);
8616 /* OK, L2 is modem */
8620 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8622 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8625 if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8627 if (plci->rx_dma_descriptor <= 0) {
8628 plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8629 if (plci->rx_dma_descriptor >= 0)
8630 plci->rx_dma_descriptor++;
8632 if (plci->rx_dma_descriptor > 0) {
8635 lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8636 lli[3] = (byte)plci->rx_dma_magic;
8637 lli[4] = (byte)(plci->rx_dma_magic >> 8);
8638 lli[5] = (byte)(plci->rx_dma_magic >> 16);
8639 lli[6] = (byte)(plci->rx_dma_magic >> 24);
8643 if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8647 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8648 /*V42*/ 10 : /*V42_IN*/ 9;
8649 llc[2] = 4; /* pass L3 always transparent */
8650 add_p(plci, LLI, lli);
8651 add_p(plci, LLC, llc);
8653 PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8655 if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8657 if (bp_parms[4].length)
8659 dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8660 dlc[i++] = 3; /* Addr A */
8661 dlc[i++] = 1; /* Addr B */
8662 dlc[i++] = 7; /* modulo mode */
8663 dlc[i++] = 7; /* window size */
8664 dlc[i++] = 0; /* XID len Lo */
8665 dlc[i++] = 0; /* XID len Hi */
8667 if (b2_config & MDM_B2_DISABLE_V42bis)
8669 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8671 if (b2_config & MDM_B2_DISABLE_MNP)
8673 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8675 if (b2_config & MDM_B2_DISABLE_TRANS)
8677 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8679 if (b2_config & MDM_B2_DISABLE_V42)
8681 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8683 if (b2_config & MDM_B2_DISABLE_COMP)
8685 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8692 dlc[i++] = 3; /* Addr A */
8693 dlc[i++] = 1; /* Addr B */
8694 dlc[i++] = 7; /* modulo mode */
8695 dlc[i++] = 7; /* window size */
8696 dlc[i++] = 0; /* XID len Lo */
8697 dlc[i++] = 0; /* XID len Hi */
8698 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8699 DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8700 DLC_MODEMPROT_DISABLE_V42_DETECT |
8701 DLC_MODEMPROT_DISABLE_COMPRESSION;
8703 dlc[0] = (byte)(i - 1);
8704 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8705 add_p(plci, DLC, dlc);
8710 /*------------------------------------------------------------------*/
8711 /* send a request for the signaling entity */
8712 /*------------------------------------------------------------------*/
8714 static void sig_req(PLCI *plci, byte req, byte Id)
8717 if(plci->adapter->adapter_disabled) return;
8718 dbug(1,dprintf("sig_req(%x)",req));
8720 plci->sig_remove_id = plci->Sig.Id;
8721 if(plci->req_in==plci->req_in_start) {
8723 plci->RBuffer[plci->req_in++] = 0;
8725 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8726 plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */
8727 plci->RBuffer[plci->req_in++] = req; /* request */
8728 plci->RBuffer[plci->req_in++] = 0; /* channel */
8729 plci->req_in_start = plci->req_in;
8732 /*------------------------------------------------------------------*/
8733 /* send a request for the network layer entity */
8734 /*------------------------------------------------------------------*/
8736 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8739 if(plci->adapter->adapter_disabled) return;
8740 dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8743 plci->nl_remove_id = plci->NL.Id;
8744 ncci_remove (plci, 0, (byte)(ncci != 0));
8747 if(plci->req_in==plci->req_in_start) {
8749 plci->RBuffer[plci->req_in++] = 0;
8751 PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8752 plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */
8753 plci->RBuffer[plci->req_in++] = req; /* request */
8754 plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */
8755 plci->req_in_start = plci->req_in;
8758 static void send_req(PLCI *plci)
8765 if(plci->adapter->adapter_disabled) return;
8766 channel_xmit_xon (plci);
8768 /* if nothing to do, return */
8769 if(plci->req_in==plci->req_out) return;
8770 dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8772 if(plci->nl_req || plci->sig_req) return;
8774 l = GET_WORD(&plci->RBuffer[plci->req_out]);
8776 plci->XData[0].P = &plci->RBuffer[plci->req_out];
8778 if(plci->RBuffer[plci->req_out]==1)
8782 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8783 e->ReqCh = plci->RBuffer[plci->req_out++];
8787 plci->RBuffer[plci->req_out-4] = CAI;
8788 plci->RBuffer[plci->req_out-3] = 1;
8789 plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8790 plci->RBuffer[plci->req_out-1] = 0;
8792 plci->nl_global_req = plci->nl_req;
8794 dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8799 if(plci->RBuffer[plci->req_out])
8800 e->Id = plci->RBuffer[plci->req_out];
8802 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8803 e->ReqCh = plci->RBuffer[plci->req_out++];
8805 plci->sig_global_req = plci->sig_req;
8806 dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8808 plci->XData[0].PLength = l;
8810 plci->adapter->request(e);
8811 dbug(1,dprintf("send_ok"));
8814 static void send_data(PLCI *plci)
8816 DIVA_CAPI_ADAPTER * a;
8817 DATA_B3_DESC * data;
8821 if (!plci->nl_req && plci->ncci_ring_list)
8824 ncci = plci->ncci_ring_list;
8827 ncci = a->ncci_next[ncci];
8828 ncci_ptr = &(a->ncci[ncci]);
8829 if (!(a->ncci_ch[ncci]
8830 && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8832 if (ncci_ptr->data_pending)
8834 if ((a->ncci_state[ncci] == CONNECTED)
8835 || (a->ncci_state[ncci] == INC_ACT_PENDING)
8836 || (plci->send_disc == ncci))
8838 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8839 if ((plci->B2_prot == B2_V120_ASYNC)
8840 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8841 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8843 plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8844 plci->NData[1].PLength = data->Length;
8845 if (data->Flags & 0x10)
8846 plci->NData[0].P = v120_break_header;
8848 plci->NData[0].P = v120_default_header;
8849 plci->NData[0].PLength = 1 ;
8851 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8855 plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8856 plci->NData[0].PLength = data->Length;
8857 if (data->Flags & 0x10)
8858 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8860 else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8861 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8864 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8866 plci->NL.X = plci->NData;
8867 plci->NL.ReqCh = a->ncci_ch[ncci];
8868 dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8869 plci->data_sent = true;
8870 plci->data_sent_ptr = data->P;
8871 a->request(&plci->NL);
8874 cleanup_ncci_data (plci, ncci);
8877 else if (plci->send_disc == ncci)
8879 /* dprintf("N_DISC"); */
8880 plci->NData[0].PLength = 0;
8881 plci->NL.ReqCh = a->ncci_ch[ncci];
8882 plci->NL.Req = plci->nl_req = N_DISC;
8883 a->request(&plci->NL);
8884 plci->command = _DISCONNECT_B3_R;
8885 plci->send_disc = 0;
8888 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8889 plci->ncci_ring_list = ncci;
8893 static void listen_check(DIVA_CAPI_ADAPTER *a)
8897 byte activnotifiedcalls = 0;
8899 dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8900 if (!remove_started && !a->adapter_disabled)
8902 for(i=0;i<a->max_plci;i++)
8904 plci = &(a->plci[i]);
8905 if(plci->notifiedcall) activnotifiedcalls++;
8907 dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8909 for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8910 if((j=get_plci(a))) {
8912 plci = &a->plci[j-1];
8913 plci->State = LISTENING;
8915 add_p(plci,OAD,"\x01\xfd");
8917 add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8919 add_p(plci,CAI,"\x01\xc0");
8920 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8921 add_p(plci,LLI,"\x01\xc4"); /* support Dummy CR FAC + MWI + SpoofNotify */
8922 add_p(plci,SHIFT|6,NULL);
8923 add_p(plci,SIN,"\x02\x00\x00");
8924 plci->internal_command = LISTEN_SIG_ASSIGN_PEND; /* do indicate_req if OK */
8925 sig_req(plci,ASSIGN,DSIG_ID);
8932 /*------------------------------------------------------------------*/
8933 /* functions for all parameters sent in INDs */
8934 /*------------------------------------------------------------------*/
8936 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8938 word ploc; /* points to current location within packet */
8950 in = plci->Sig.RBuffer->P;
8951 for(i=0; i<parms_id[0]; i++) /* multiIE parms_id contains just the 1st */
8952 { /* element but parms array is larger */
8953 parms[i] = (byte *)"";
8955 for(i=0; i<multiIEsize; i++)
8957 parms[i] = (byte *)"";
8960 while(ploc<plci->Sig.RBuffer->length-1) {
8962 /* read information element id and length */
8966 /* w &=0xf0; removed, cannot detect congestion levels */
8967 /* upper 4 bit masked with w==SHIFT now */
8971 wlen = (byte)(in[ploc+1]+1);
8973 /* check if length valid (not exceeding end of packet) */
8974 if((ploc+wlen) > 270) return ;
8975 if(lock & 0x80) lock &=0x7f;
8976 else codeset = lock;
8978 if((w&0xf0)==SHIFT) {
8980 if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8985 if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8987 code |= (codeset<<8);
8989 for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8991 if(i<parms_id[0]+1) {
8992 if(!multiIEsize) { /* with multiIEs use next field index, */
8993 mIEindex = i-1; /* with normal IEs use same index like parms_id */
8996 parms[mIEindex] = &in[ploc+1];
8997 dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8999 || parms_id[i]==CONN_NR
9000 || parms_id[i]==CAD) {
9001 if(in[ploc+2] &0x80) {
9002 in[ploc+0] = (byte)(in[ploc+1]+1);
9003 in[ploc+1] = (byte)(in[ploc+2] &0x7f);
9005 parms[mIEindex] = &in[ploc];
9008 mIEindex++; /* effects multiIEs only */
9017 /*------------------------------------------------------------------*/
9018 /* try to match a cip from received BC and HLC */
9019 /*------------------------------------------------------------------*/
9021 static byte ie_compare(byte *ie1, byte *ie2)
9024 if(!ie1 || ! ie2) return false;
9025 if(!ie1[0]) return false;
9026 for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9030 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9035 for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9038 (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9044 static byte AddInfo(byte **add_i,
9054 /* facility is a nested structure */
9055 /* FTY can be more than once */
9057 if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9059 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9064 add_i[0] = (byte *)"";
9068 add_i[3] = (byte *)"";
9071 { /* facility array found */
9072 for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9074 dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9078 facility[j++]=0x1c; /* copy fac IE */
9079 for(k=0;k<=flen;k++,j++)
9081 facility[j]=fty_i[i][k];
9082 /* dbug(1,dprintf("%x ",facility[j])); */
9086 add_i[3] = facility;
9088 /* dbug(1,dprintf("FacArrLen=%d ",len)); */
9089 len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9090 len += 4; /* calculate length of all */
9094 /*------------------------------------------------------------------*/
9095 /* voice and codec features */
9096 /*------------------------------------------------------------------*/
9098 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9100 byte voice_chi[] = "\x02\x18\x01";
9103 channel = chi[chi[0]]&0x3;
9104 dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9105 voice_chi[2] = (channel) ? channel : 1;
9106 add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */
9107 add_p(plci,ESC,voice_chi); /* Channel */
9108 sig_req(plci,TEL_CTRL,0);
9110 if(a->AdvSignalPLCI)
9112 adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9116 static void VoiceChannelOff(PLCI *plci)
9118 dbug(1,dprintf("ExtDevOFF"));
9119 add_p(plci,FTY,"\x02\x01\x08"); /* B Off */
9120 sig_req(plci,TEL_CTRL,0);
9122 if(plci->adapter->AdvSignalPLCI)
9124 adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9129 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9135 /* check if hardware supports handset with hook states (adv.codec) */
9136 /* or if just a on board codec is supported */
9137 /* the advanced codec plci is just for internal use */
9139 /* diva Pro with on-board codec: */
9140 if(a->profile.Global_Options & HANDSET)
9142 /* new call, but hook states are already signalled */
9145 if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9147 dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9148 return 0x2001; /* codec in use by another application */
9152 a->AdvSignalPLCI = plci;
9153 plci->tel=ADV_VOICE;
9155 return 0; /* adv codec still used */
9159 splci = &a->plci[j-1];
9160 splci->tel = CODEC_PERMANENT;
9161 /* hook_listen indicates if a facility_req with handset/hook support */
9162 /* was sent. Otherwise if just a call on an external device was made */
9163 /* the codec will be used but the hook info will be discarded (just */
9164 /* the external controller is in use */
9165 if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9168 splci->State = ADVANCED_VOICE_NOSIG;
9171 plci->spoofed_msg = SPOOFING_REQUIRED;
9173 /* indicate D-ch connect if */
9174 } /* codec is connected OK */
9177 a->AdvSignalPLCI = plci;
9178 plci->tel=ADV_VOICE;
9180 a->AdvSignalAppl = appl;
9181 a->AdvCodecFLAG = true;
9182 a->AdvCodecPLCI = splci;
9183 add_p(splci,CAI,"\x01\x15");
9184 add_p(splci,LLI,"\x01\x00");
9185 add_p(splci,ESC,"\x02\x18\x00");
9186 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9187 splci->internal_command = PERM_COD_ASSIGN;
9188 dbug(1,dprintf("Codec Assign"));
9189 sig_req(splci,ASSIGN,DSIG_ID);
9194 return 0x2001; /* wrong state, no more plcis */
9197 else if(a->profile.Global_Options & ON_BOARD_CODEC)
9199 if(hook_listen) return 0x300B; /* Facility not supported */
9200 /* no hook with SCOM */
9201 if(plci!=NULL) plci->tel = CODEC;
9202 dbug(1,dprintf("S/SCOM codec"));
9203 /* first time we use the scom-s codec we must shut down the internal */
9204 /* handset application of the card. This can be done by an assign with */
9205 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9206 if(!a->scom_appl_disable){
9207 if((j=get_plci(a))) {
9208 splci = &a->plci[j-1];
9209 add_p(splci,CAI,"\x01\x80");
9210 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9211 sig_req(splci,ASSIGN,0xC0); /* 0xc0 is the TEL_ID */
9213 a->scom_appl_disable = true;
9216 return 0x2001; /* wrong state, no more plcis */
9220 else return 0x300B; /* Facility not supported */
9226 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9229 dbug(1,dprintf("CodecIdCheck"));
9231 if(a->AdvSignalPLCI == plci)
9233 dbug(1,dprintf("PLCI owns codec"));
9234 VoiceChannelOff(a->AdvCodecPLCI);
9235 if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9237 dbug(1,dprintf("remove temp codec PLCI"));
9238 plci_remove(a->AdvCodecPLCI);
9239 a->AdvCodecFLAG = 0;
9240 a->AdvCodecPLCI = NULL;
9241 a->AdvSignalAppl = NULL;
9243 a->AdvSignalPLCI = NULL;
9247 /* -------------------------------------------------------------------
9248 Ask for physical address of card on PCI bus
9249 ------------------------------------------------------------------- */
9250 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER * a,
9251 IDI_SYNC_REQ * preq) {
9253 if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9254 ENTITY * e = (ENTITY *)preq;
9256 e->user[0] = a->Id - 1;
9257 preq->xdi_sdram_bar.info.bar = 0;
9258 preq->xdi_sdram_bar.Req = 0;
9259 preq->xdi_sdram_bar.Rc = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9263 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9264 dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9268 /* -------------------------------------------------------------------
9269 Ask XDI about extended features
9270 ------------------------------------------------------------------- */
9271 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER * a) {
9272 IDI_SYNC_REQ * preq;
9273 char buffer[ ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9276 preq = (IDI_SYNC_REQ *)&buffer[0];
9278 if (!diva_xdi_extended_features) {
9279 ENTITY * e = (ENTITY *)preq;
9280 diva_xdi_extended_features |= 0x80000000;
9282 e->user[0] = a->Id - 1;
9283 preq->xdi_extended_features.Req = 0;
9284 preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9285 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9286 preq->xdi_extended_features.info.features = &features[0];
9290 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9292 Check features located in the byte '0'
9294 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9295 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9297 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9298 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9299 dbug(1,dprintf("XDI provides RxDMA"));
9301 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9302 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9304 if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9305 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9306 dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9312 diva_ask_for_xdi_sdram_bar (a, preq);
9315 /*------------------------------------------------------------------*/
9317 /*------------------------------------------------------------------*/
9318 /* called from OS specific part after init time to get the Law */
9319 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9320 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9325 if(a->automatic_law) {
9328 if((j=get_plci(a))) {
9329 diva_get_extended_adapter_features (a);
9330 splci = &a->plci[j-1];
9331 a->automatic_lawPLCI = splci;
9332 a->automatic_law = 1;
9333 add_p(splci,CAI,"\x01\x80");
9334 add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9335 splci->internal_command = USELAW_REQ;
9338 sig_req(splci,ASSIGN,DSIG_ID);
9343 /* called from OS specific part if an application sends an Capi20Release */
9344 word CapiRelease(word Id)
9346 word i, j, appls_found;
9349 DIVA_CAPI_ADAPTER *a;
9353 dbug(0,dprintf("A: CapiRelease(Id==0)"));
9354 return (_WRONG_APPL_ID);
9357 this = &application[Id-1]; /* get application pointer */
9359 for(i=0,appls_found=0; i<max_appl; i++)
9361 if(application[i].Id) /* an application has been found */
9367 for(i=0; i<max_adapter; i++) /* scan all adapters... */
9372 a->Info_Mask[Id-1] = 0;
9373 a->CIP_Mask[Id-1] = 0;
9374 a->Notification_Mask[Id-1] = 0;
9375 a->codec_listen[Id-1] = NULL;
9376 a->requested_options_table[Id-1] = 0;
9377 for(j=0; j<a->max_plci; j++) /* and all PLCIs connected */
9378 { /* with this application */
9380 if(plci->Id) /* if plci owns no application */
9381 { /* it may be not jet connected */
9382 if(plci->State==INC_CON_PENDING
9383 || plci->State==INC_CON_ALERT)
9385 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9387 clear_c_ind_mask_bit (plci, (word)(Id-1));
9388 if(c_ind_mask_empty (plci))
9390 sig_req(plci,HANGUP,0);
9392 plci->State = OUTG_DIS_PENDING;
9396 if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9398 clear_c_ind_mask_bit (plci, (word)(Id-1));
9399 if(c_ind_mask_empty (plci))
9408 if(plci->appl==this)
9418 if(a->flag_dynamic_l1_down)
9420 if(appls_found==1) /* last application does a capi release */
9424 plci = &a->plci[j-1];
9426 add_p(plci,OAD,"\x01\xfd");
9427 add_p(plci,CAI,"\x01\x80");
9428 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9429 add_p(plci,SHIFT|6,NULL);
9430 add_p(plci,SIN,"\x02\x00\x00");
9431 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9432 sig_req(plci,ASSIGN,DSIG_ID);
9433 add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9434 sig_req(plci,SIG_CTRL,0);
9439 if(a->AdvSignalAppl==this)
9441 this->NullCREnable = false;
9442 if (a->AdvCodecPLCI)
9444 plci_remove(a->AdvCodecPLCI);
9445 a->AdvCodecPLCI->tel = 0;
9446 a->AdvCodecPLCI->adv_nl = 0;
9448 a->AdvSignalAppl = NULL;
9449 a->AdvSignalPLCI = NULL;
9450 a->AdvCodecFLAG = 0;
9451 a->AdvCodecPLCI = NULL;
9461 static word plci_remove_check(PLCI *plci)
9463 if(!plci) return true;
9464 if(!plci->NL.Id && c_ind_mask_empty (plci))
9466 if(plci->Sig.Id == 0xff)
9470 dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9471 dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9474 CodecIdCheck(plci->adapter, plci);
9475 clear_b1_config (plci);
9476 ncci_remove (plci, 0, false);
9477 plci_free_msg_in_queue (plci);
9478 channel_flow_control_remove (plci);
9483 plci->notifiedcall = 0;
9485 listen_check(plci->adapter);
9493 /*------------------------------------------------------------------*/
9495 static byte plci_nl_busy (PLCI *plci)
9497 /* only applicable for non-multiplexed protocols */
9498 return (plci->nl_req
9499 || (plci->ncci_ring_list
9500 && plci->adapter->ncci_ch[plci->ncci_ring_list]
9501 && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9505 /*------------------------------------------------------------------*/
9506 /* DTMF facilities */
9507 /*------------------------------------------------------------------*/
9516 } dtmf_digit_map[] =
9518 { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9519 { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9520 { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9521 { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9522 { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9523 { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9524 { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9525 { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9526 { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9527 { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9528 { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9529 { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9530 { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9531 { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9532 { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9533 { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9534 { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9535 { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9536 { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9537 { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9539 { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9540 { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9541 { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9542 { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9543 { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9544 { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9545 { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9546 { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9547 { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9548 { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9549 { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9550 { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9551 { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9552 { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9553 { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9554 { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9555 { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9556 { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9557 { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9558 { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9559 { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9560 { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9561 { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9562 { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9563 { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9564 { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9565 { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9566 { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9567 { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9568 { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9569 { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9570 { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9571 { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9572 { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9573 { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9574 { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9575 { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9576 { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9577 { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9578 { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9579 { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9580 { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9581 { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9582 { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9583 { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9584 { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9585 { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9586 { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9587 { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9588 { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9589 { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9590 { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9594 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9597 static void dtmf_enable_receiver (PLCI *plci, byte enable_mask)
9599 word min_digit_duration, min_gap_duration;
9601 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9602 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9603 (char *)(FILE_), __LINE__, enable_mask));
9605 if (enable_mask != 0)
9607 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9608 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9609 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9610 PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9611 PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9612 plci->NData[0].PLength = 5;
9614 PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9615 plci->NData[0].PLength += 2;
9616 capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9621 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9622 plci->NData[0].PLength = 1;
9624 capidtmf_recv_disable (&(plci->capidtmf_state));
9627 plci->NData[0].P = plci->internal_req_buffer;
9628 plci->NL.X = plci->NData;
9630 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9631 plci->adapter->request (&plci->NL);
9635 static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_count)
9639 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9640 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9641 (char *)(FILE_), __LINE__, digit_count));
9643 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9644 w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9645 PUT_WORD (&plci->internal_req_buffer[1], w);
9646 w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9647 PUT_WORD (&plci->internal_req_buffer[3], w);
9648 for (i = 0; i < digit_count; i++)
9651 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9652 && (digit_buffer[i] != dtmf_digit_map[w].character))
9656 plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9657 dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9659 plci->NData[0].PLength = 5 + digit_count;
9660 plci->NData[0].P = plci->internal_req_buffer;
9661 plci->NL.X = plci->NData;
9663 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9664 plci->adapter->request (&plci->NL);
9668 static void dtmf_rec_clear_config (PLCI *plci)
9671 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9672 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9673 (char *)(FILE_), __LINE__));
9675 plci->dtmf_rec_active = 0;
9676 plci->dtmf_rec_pulse_ms = 0;
9677 plci->dtmf_rec_pause_ms = 0;
9679 capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9684 static void dtmf_send_clear_config (PLCI *plci)
9687 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9688 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9689 (char *)(FILE_), __LINE__));
9691 plci->dtmf_send_requests = 0;
9692 plci->dtmf_send_pulse_ms = 0;
9693 plci->dtmf_send_pause_ms = 0;
9697 static void dtmf_prepare_switch (dword Id, PLCI *plci)
9700 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9701 UnMapId (Id), (char *)(FILE_), __LINE__));
9703 while (plci->dtmf_send_requests != 0)
9704 dtmf_confirmation (Id, plci);
9708 static word dtmf_save_config (dword Id, PLCI *plci, byte Rc)
9711 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9712 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9718 static word dtmf_restore_config (dword Id, PLCI *plci, byte Rc)
9722 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9723 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9726 if (plci->B1_facilities & B1_FACILITY_DTMFR)
9728 switch (plci->adjust_b_state)
9730 case ADJUST_B_RESTORE_DTMF_1:
9731 plci->internal_command = plci->adjust_b_command;
9732 if (plci_nl_busy (plci))
9734 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9737 dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9738 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9740 case ADJUST_B_RESTORE_DTMF_2:
9741 if ((Rc != OK) && (Rc != OK_FC))
9743 dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9744 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9745 Info = _WRONG_STATE;
9755 static void dtmf_command (dword Id, PLCI *plci, byte Rc)
9757 word internal_command, Info;
9761 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9762 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9763 plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9764 plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9768 PUT_WORD (&result[1], DTMF_SUCCESS);
9769 internal_command = plci->internal_command;
9770 plci->internal_command = 0;
9772 switch (plci->dtmf_cmd)
9775 case DTMF_LISTEN_TONE_START:
9777 case DTMF_LISTEN_MF_START:
9780 case DTMF_LISTEN_START:
9781 switch (internal_command)
9784 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9785 B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9786 case DTMF_COMMAND_1:
9787 if (adjust_b_process (Id, plci, Rc) != GOOD)
9789 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9790 UnMapId (Id), (char *)(FILE_), __LINE__));
9791 Info = _FACILITY_NOT_SUPPORTED;
9794 if (plci->internal_command)
9796 case DTMF_COMMAND_2:
9797 if (plci_nl_busy (plci))
9799 plci->internal_command = DTMF_COMMAND_2;
9802 plci->internal_command = DTMF_COMMAND_3;
9803 dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9805 case DTMF_COMMAND_3:
9806 if ((Rc != OK) && (Rc != OK_FC))
9808 dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9809 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9810 Info = _FACILITY_NOT_SUPPORTED;
9814 plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9816 plci->dtmf_rec_active |= mask;
9822 case DTMF_LISTEN_TONE_STOP:
9824 case DTMF_LISTEN_MF_STOP:
9827 case DTMF_LISTEN_STOP:
9828 switch (internal_command)
9831 plci->dtmf_rec_active &= ~mask;
9832 if (plci->dtmf_rec_active)
9835 case DTMF_COMMAND_1:
9836 if (plci->dtmf_rec_active)
9838 if (plci_nl_busy (plci))
9840 plci->internal_command = DTMF_COMMAND_1;
9843 plci->dtmf_rec_active &= ~mask;
9844 plci->internal_command = DTMF_COMMAND_2;
9845 dtmf_enable_receiver (plci, false);
9849 case DTMF_COMMAND_2:
9850 if ((Rc != OK) && (Rc != OK_FC))
9852 dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9853 UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9854 Info = _FACILITY_NOT_SUPPORTED;
9858 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9859 ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9860 case DTMF_COMMAND_3:
9861 if (adjust_b_process (Id, plci, Rc) != GOOD)
9863 dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9864 UnMapId (Id), (char *)(FILE_), __LINE__));
9865 Info = _FACILITY_NOT_SUPPORTED;
9868 if (plci->internal_command)
9875 case DTMF_SEND_TONE:
9880 case DTMF_DIGITS_SEND:
9881 switch (internal_command)
9884 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9885 ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9887 case DTMF_COMMAND_1:
9888 if (adjust_b_process (Id, plci, Rc) != GOOD)
9890 dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9891 UnMapId (Id), (char *)(FILE_), __LINE__));
9892 Info = _FACILITY_NOT_SUPPORTED;
9895 if (plci->internal_command)
9897 case DTMF_COMMAND_2:
9898 if (plci_nl_busy (plci))
9900 plci->internal_command = DTMF_COMMAND_2;
9903 plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9904 plci->internal_command = DTMF_COMMAND_3;
9905 dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9907 case DTMF_COMMAND_3:
9908 if ((Rc != OK) && (Rc != OK_FC))
9910 dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9911 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
9912 if (plci->dtmf_send_requests != 0)
9913 (plci->dtmf_send_requests)--;
9914 Info = _FACILITY_NOT_SUPPORTED;
9921 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9922 "wws", Info, SELECTOR_DTMF, result);
9926 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
9931 API_PARSE dtmf_parms[5];
9934 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9935 UnMapId (Id), (char *)(FILE_), __LINE__));
9939 PUT_WORD (&result[1], DTMF_SUCCESS);
9940 if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9942 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9943 UnMapId (Id), (char *)(FILE_), __LINE__));
9944 Info = _FACILITY_NOT_SUPPORTED;
9946 else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9948 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9949 UnMapId (Id), (char *)(FILE_), __LINE__));
9950 Info = _WRONG_MESSAGE_FORMAT;
9953 else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9954 || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9956 if (!((a->requested_options_table[appl->Id-1])
9957 & (1L << PRIVATE_DTMF_TONE)))
9959 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9960 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9961 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9965 for (i = 0; i < 32; i++)
9967 if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9969 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9971 if (dtmf_digit_map[i].listen_mask != 0)
9972 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9977 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9979 if (dtmf_digit_map[i].send_mask != 0)
9980 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9988 else if (plci == NULL)
9990 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9991 UnMapId (Id), (char *)(FILE_), __LINE__));
9992 Info = _WRONG_IDENTIFIER;
9997 || !plci->NL.Id || plci->nl_remove_id)
9999 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
10000 UnMapId (Id), (char *)(FILE_), __LINE__));
10001 Info = _WRONG_STATE;
10006 plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
10008 switch (plci->dtmf_cmd)
10011 case DTMF_LISTEN_TONE_START:
10012 case DTMF_LISTEN_TONE_STOP:
10014 case DTMF_LISTEN_MF_START:
10015 case DTMF_LISTEN_MF_STOP:
10017 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10018 & (1L << PRIVATE_DTMF_TONE)))
10020 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10021 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10022 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10026 case DTMF_LISTEN_START:
10027 case DTMF_LISTEN_STOP:
10028 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10029 && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10031 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10032 UnMapId (Id), (char *)(FILE_), __LINE__));
10033 Info = _FACILITY_NOT_SUPPORTED;
10036 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10038 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10040 plci->dtmf_rec_pulse_ms = 0;
10041 plci->dtmf_rec_pause_ms = 0;
10045 plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10046 plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10049 start_internal_command (Id, plci, dtmf_command);
10053 case DTMF_SEND_TONE:
10057 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10058 & (1L << PRIVATE_DTMF_TONE)))
10060 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10061 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10062 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10066 case DTMF_DIGITS_SEND:
10067 if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10069 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10070 UnMapId (Id), (char *)(FILE_), __LINE__));
10071 Info = _WRONG_MESSAGE_FORMAT;
10074 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10076 plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10077 plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10081 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10084 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10085 && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10086 || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10092 if (j == DTMF_DIGIT_MAP_ENTRIES)
10094 dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10095 UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10096 PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10099 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10101 dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10102 UnMapId (Id), (char *)(FILE_), __LINE__));
10103 Info = _WRONG_STATE;
10106 api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10107 start_internal_command (Id, plci, dtmf_command);
10111 dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10112 UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10113 PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10117 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10118 "wws", Info, SELECTOR_DTMF, result);
10123 static void dtmf_confirmation (dword Id, PLCI *plci)
10129 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10130 UnMapId (Id), (char *)(FILE_), __LINE__));
10134 PUT_WORD (&result[1], DTMF_SUCCESS);
10135 if (plci->dtmf_send_requests != 0)
10137 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10138 "wws", GOOD, SELECTOR_DTMF, result);
10139 (plci->dtmf_send_requests)--;
10140 for (i = 0; i < plci->dtmf_send_requests; i++)
10141 plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];
10146 static void dtmf_indication (dword Id, PLCI *plci, byte *msg, word length)
10150 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10151 UnMapId (Id), (char *)(FILE_), __LINE__));
10154 for (i = 1; i < length; i++)
10157 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10158 && ((msg[i] != dtmf_digit_map[j].code)
10159 || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10163 if (j < DTMF_DIGIT_MAP_ENTRIES)
10166 if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10167 && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10168 && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10172 for (i = length; i > n + 1; i--)
10173 msg[i] = msg[i - 1];
10177 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10179 plci->tone_last_indication_code = dtmf_digit_map[j].character;
10181 msg[++n] = dtmf_digit_map[j].character;
10187 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10192 /*------------------------------------------------------------------*/
10193 /* DTMF parameters */
10194 /*------------------------------------------------------------------*/
10196 static void dtmf_parameter_write (PLCI *plci)
10199 byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10201 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10202 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10203 (char *)(FILE_), __LINE__));
10205 parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10206 parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10207 for (i = 0; i < plci->dtmf_parameter_length; i++)
10208 parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10209 add_p (plci, FTY, parameter_buffer);
10210 sig_req (plci, TEL_CTRL, 0);
10215 static void dtmf_parameter_clear_config (PLCI *plci)
10218 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10219 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10220 (char *)(FILE_), __LINE__));
10222 plci->dtmf_parameter_length = 0;
10226 static void dtmf_parameter_prepare_switch (dword Id, PLCI *plci)
10229 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10230 UnMapId (Id), (char *)(FILE_), __LINE__));
10235 static word dtmf_parameter_save_config (dword Id, PLCI *plci, byte Rc)
10238 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10239 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10245 static word dtmf_parameter_restore_config (dword Id, PLCI *plci, byte Rc)
10249 dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10250 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10253 if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10254 && (plci->dtmf_parameter_length != 0))
10256 switch (plci->adjust_b_state)
10258 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10259 plci->internal_command = plci->adjust_b_command;
10262 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10265 dtmf_parameter_write (plci);
10266 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10268 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10269 if ((Rc != OK) && (Rc != OK_FC))
10271 dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10272 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10273 Info = _WRONG_STATE;
10283 /*------------------------------------------------------------------*/
10284 /* Line interconnect facilities */
10285 /*------------------------------------------------------------------*/
10288 LI_CONFIG *li_config_table;
10289 word li_total_channels;
10292 /*------------------------------------------------------------------*/
10293 /* translate a CHI information element to a channel number */
10294 /* returns 0xff - any channel */
10295 /* 0xfe - chi wrong coding */
10296 /* 0xfd - D-channel */
10297 /* 0x00 - no channel */
10298 /* else channel number / PRI: timeslot */
10299 /* if channels is provided we accept more than one channel. */
10300 /*------------------------------------------------------------------*/
10302 static byte chi_to_channel (byte *chi, dword *pchannelmap)
10311 if (pchannelmap) *pchannelmap = 0;
10312 if(!chi[0]) return 0xff;
10315 if(chi[1] & 0x20) {
10316 if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10317 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10318 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10319 if((chi[1] |0xc8)!=0xe9) return 0xfe;
10320 if(chi[1] &0x08) excl = 0x40;
10322 /* int. id present */
10325 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10326 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10329 /* coding standard, Number/Map, Channel Type */
10331 for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10332 if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10333 if((chi[p]|0xd0)!=0xd3) return 0xfe;
10339 if((chi[0]-p)==4) ofs = 0;
10340 else if((chi[0]-p)==3) ofs = 1;
10344 for(i=0; i<4 && p<chi[0]; i++) {
10349 for (ch=0; !(chi[p] & (1 << ch)); ch++);
10362 if((byte)(chi[0]-p)>30) return 0xfe;
10364 for(i=p; i<=chi[0]; i++) {
10365 if ((chi[i] &0x7f) > 31) return 0xfe;
10366 map |= (1L << (chi[i] &0x7f));
10370 if(p!=chi[0]) return 0xfe;
10371 if (ch > 31) return 0xfe;
10374 if(chi[p] &0x40) return 0xfe;
10376 if (pchannelmap) *pchannelmap = map;
10377 else if (map != ((dword)(1L << ch))) return 0xfe;
10378 return (byte)(excl | ch);
10380 else { /* not PRI */
10381 for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10382 if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10383 if(chi[1] &0x08) excl = 0x40;
10385 switch(chi[1] |0x98) {
10386 case 0x98: return 0;
10388 if (pchannelmap) *pchannelmap = 2;
10391 if (pchannelmap) *pchannelmap = 4;
10393 case 0x9b: return 0xff;
10394 case 0x9c: return 0xfd; /* d-ch */
10395 default: return 0xfe;
10401 static void mixer_set_bchannel_id_esc (PLCI *plci, byte bchannel_id)
10403 DIVA_CAPI_ADAPTER *a;
10408 old_id = plci->li_bchannel_id;
10411 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10412 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10413 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10414 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10415 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10419 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10421 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10422 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10423 plci->li_bchannel_id = bchannel_id & 0x03;
10424 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10426 splci = a->AdvSignalPLCI;
10427 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10429 if ((splci->li_bchannel_id != 0)
10430 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10432 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10434 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10435 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10436 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10437 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10438 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10441 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10442 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10445 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10446 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10448 mixer_clear_config (plci);
10450 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10451 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10452 (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10456 static void mixer_set_bchannel_id (PLCI *plci, byte *chi)
10458 DIVA_CAPI_ADAPTER *a;
10463 old_id = plci->li_bchannel_id;
10464 ch = chi_to_channel (chi, NULL);
10469 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10470 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10471 plci->li_bchannel_id = (ch & 0x1f) + 1;
10472 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10473 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10477 if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10479 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10480 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10481 plci->li_bchannel_id = ch & 0x1f;
10482 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10484 splci = a->AdvSignalPLCI;
10485 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10487 if ((splci->li_bchannel_id != 0)
10488 && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10490 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10492 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10493 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10494 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10495 (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10496 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10499 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10500 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10504 if ((old_id == 0) && (plci->li_bchannel_id != 0)
10505 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10507 mixer_clear_config (plci);
10509 dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10510 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10511 (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10515 #define MIXER_MAX_DUMP_CHANNELS 34
10517 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER *a)
10519 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10522 char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10524 dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10525 (dword)(UnMapController (a->Id)), (char *)(FILE_), __LINE__));
10527 for (i = 0; i < li_total_channels; i++)
10529 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10530 if (li_config_table[i].chflags != 0)
10531 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10534 for (j = 0; j < li_total_channels; j++)
10536 if (((li_config_table[i].flag_table[j]) != 0)
10537 || ((li_config_table[j].flag_table[i]) != 0))
10539 li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10541 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10542 || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10544 li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10549 for (i = 0; i < li_total_channels; i++)
10551 for (j = 0; j < li_total_channels; j++)
10553 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10554 if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10555 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10558 for (n = 0; n < li_total_channels; n++)
10560 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10562 for (i = 0; i < li_total_channels; i++)
10564 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10566 for (j = 0; j < li_total_channels; j++)
10568 li_config_table[i].coef_table[j] |=
10569 li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10575 for (i = 0; i < li_total_channels; i++)
10577 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10579 li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10580 for (j = 0; j < li_total_channels; j++)
10582 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10583 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10585 if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10586 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10589 for (i = 0; i < li_total_channels; i++)
10591 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10593 for (j = 0; j < li_total_channels; j++)
10595 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10596 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10597 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10598 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10599 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10600 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10601 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10602 li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10604 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10606 for (j = 0; j < li_total_channels; j++)
10608 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10610 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10611 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10612 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10616 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10618 for (j = 0; j < li_total_channels; j++)
10620 if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10621 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10624 if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10626 for (j = 0; j < li_total_channels; j++)
10628 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10630 for (n = 0; n < li_total_channels; n++)
10632 if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10634 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10635 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10637 li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10638 if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10639 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10641 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10642 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10650 for (i = 0; i < li_total_channels; i++)
10652 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10654 if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10655 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10656 if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10657 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10658 if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10659 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10660 for (j = 0; j < li_total_channels; j++)
10662 if ((li_config_table[i].flag_table[j] &
10663 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10664 || (li_config_table[j].flag_table[i] &
10665 (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10667 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10669 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10670 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10671 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10672 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10674 if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10676 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10677 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10681 for (i = 0; i < li_total_channels; i++)
10683 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10686 while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10688 if (j < li_total_channels)
10690 for (j = 0; j < li_total_channels; j++)
10692 li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10693 if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10694 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10699 n = li_total_channels;
10700 if (n > MIXER_MAX_DUMP_CHANNELS)
10701 n = MIXER_MAX_DUMP_CHANNELS;
10703 for (j = 0; j < n; j++)
10705 if ((j & 0x7) == 0)
10707 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10708 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10711 dbug (1, dprintf ("[%06lx] CURRENT %s",
10712 (dword)(UnMapController (a->Id)), (char *) hex_line));
10714 for (j = 0; j < n; j++)
10716 if ((j & 0x7) == 0)
10718 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10719 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10722 dbug (1, dprintf ("[%06lx] CHANNEL %s",
10723 (dword)(UnMapController (a->Id)), (char *) hex_line));
10725 for (j = 0; j < n; j++)
10727 if ((j & 0x7) == 0)
10729 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10730 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10733 dbug (1, dprintf ("[%06lx] CHFLAG %s",
10734 (dword)(UnMapController (a->Id)), (char *) hex_line));
10735 for (i = 0; i < n; i++)
10738 for (j = 0; j < n; j++)
10740 if ((j & 0x7) == 0)
10742 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10743 *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10746 dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10747 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10749 for (i = 0; i < n; i++)
10752 for (j = 0; j < n; j++)
10754 if ((j & 0x7) == 0)
10756 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10757 *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10760 dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10761 (dword)(UnMapController (a->Id)), i, (char *) hex_line));
10770 } mixer_write_prog_pri[] =
10772 { LI_COEF_CH_CH, 0 },
10773 { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10774 { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10775 { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10783 byte xconnect_override;
10784 } mixer_write_prog_bri[] =
10786 { 0, 0, LI_COEF_CH_CH, 0x01 }, /* B to B */
10787 { 1, 0, LI_COEF_CH_CH, 0x01 }, /* Alt B to B */
10788 { 0, 0, LI_COEF_PC_CH, 0x80 }, /* PC to B */
10789 { 1, 0, LI_COEF_PC_CH, 0x01 }, /* Alt PC to B */
10790 { 2, 0, LI_COEF_CH_CH, 0x00 }, /* IC to B */
10791 { 3, 0, LI_COEF_CH_CH, 0x00 }, /* Alt IC to B */
10792 { 0, 0, LI_COEF_CH_PC, 0x80 }, /* B to PC */
10793 { 1, 0, LI_COEF_CH_PC, 0x01 }, /* Alt B to PC */
10794 { 0, 0, LI_COEF_PC_PC, 0x01 }, /* PC to PC */
10795 { 1, 0, LI_COEF_PC_PC, 0x01 }, /* Alt PC to PC */
10796 { 2, 0, LI_COEF_CH_PC, 0x00 }, /* IC to PC */
10797 { 3, 0, LI_COEF_CH_PC, 0x00 }, /* Alt IC to PC */
10798 { 0, 2, LI_COEF_CH_CH, 0x00 }, /* B to IC */
10799 { 1, 2, LI_COEF_CH_CH, 0x00 }, /* Alt B to IC */
10800 { 0, 2, LI_COEF_PC_CH, 0x00 }, /* PC to IC */
10801 { 1, 2, LI_COEF_PC_CH, 0x00 }, /* Alt PC to IC */
10802 { 2, 2, LI_COEF_CH_CH, 0x00 }, /* IC to IC */
10803 { 3, 2, LI_COEF_CH_CH, 0x00 }, /* Alt IC to IC */
10804 { 1, 1, LI_COEF_CH_CH, 0x01 }, /* Alt B to Alt B */
10805 { 0, 1, LI_COEF_CH_CH, 0x01 }, /* B to Alt B */
10806 { 1, 1, LI_COEF_PC_CH, 0x80 }, /* Alt PC to Alt B */
10807 { 0, 1, LI_COEF_PC_CH, 0x01 }, /* PC to Alt B */
10808 { 3, 1, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt B */
10809 { 2, 1, LI_COEF_CH_CH, 0x00 }, /* IC to Alt B */
10810 { 1, 1, LI_COEF_CH_PC, 0x80 }, /* Alt B to Alt PC */
10811 { 0, 1, LI_COEF_CH_PC, 0x01 }, /* B to Alt PC */
10812 { 1, 1, LI_COEF_PC_PC, 0x01 }, /* Alt PC to Alt PC */
10813 { 0, 1, LI_COEF_PC_PC, 0x01 }, /* PC to Alt PC */
10814 { 3, 1, LI_COEF_CH_PC, 0x00 }, /* Alt IC to Alt PC */
10815 { 2, 1, LI_COEF_CH_PC, 0x00 }, /* IC to Alt PC */
10816 { 1, 3, LI_COEF_CH_CH, 0x00 }, /* Alt B to Alt IC */
10817 { 0, 3, LI_COEF_CH_CH, 0x00 }, /* B to Alt IC */
10818 { 1, 3, LI_COEF_PC_CH, 0x00 }, /* Alt PC to Alt IC */
10819 { 0, 3, LI_COEF_PC_CH, 0x00 }, /* PC to Alt IC */
10820 { 3, 3, LI_COEF_CH_CH, 0x00 }, /* Alt IC to Alt IC */
10821 { 2, 3, LI_COEF_CH_CH, 0x00 } /* IC to Alt IC */
10824 static byte mixer_swapped_index_bri[] =
10827 19, /* Alt B to B */
10829 21, /* Alt PC to B */
10831 23, /* Alt IC to B */
10833 25, /* Alt B to PC */
10835 27, /* Alt PC to PC */
10837 29, /* Alt IC to PC */
10839 31, /* Alt B to IC */
10841 33, /* Alt PC to IC */
10843 35, /* Alt IC to IC */
10844 0, /* Alt B to Alt B */
10845 1, /* B to Alt B */
10846 2, /* Alt PC to Alt B */
10847 3, /* PC to Alt B */
10848 4, /* Alt IC to Alt B */
10849 5, /* IC to Alt B */
10850 6, /* Alt B to Alt PC */
10851 7, /* B to Alt PC */
10852 8, /* Alt PC to Alt PC */
10853 9, /* PC to Alt PC */
10854 10, /* Alt IC to Alt PC */
10855 11, /* IC to Alt PC */
10856 12, /* Alt B to Alt IC */
10857 13, /* B to Alt IC */
10858 14, /* Alt PC to Alt IC */
10859 15, /* PC to Alt IC */
10860 16, /* Alt IC to Alt IC */
10861 17 /* IC to Alt IC */
10869 } xconnect_write_prog[] =
10871 { LI_COEF_CH_CH, false, false },
10872 { LI_COEF_CH_PC, false, true },
10873 { LI_COEF_PC_CH, true, false },
10874 { LI_COEF_PC_PC, true, true }
10878 static void xconnect_query_addresses (PLCI *plci)
10880 DIVA_CAPI_ADAPTER *a;
10884 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10885 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10886 (char *)(FILE_), __LINE__));
10889 if (a->li_pri && ((plci->li_bchannel_id == 0)
10890 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10892 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10893 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10894 (char *)(FILE_), __LINE__));
10897 p = plci->internal_req_buffer;
10898 ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10899 *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10902 *(p++) = (byte)(w >> 8);
10903 w = ch | XCONNECT_CHANNEL_PORT_PC;
10905 *(p++) = (byte)(w >> 8);
10906 plci->NData[0].P = plci->internal_req_buffer;
10907 plci->NData[0].PLength = p - plci->internal_req_buffer;
10908 plci->NL.X = plci->NData;
10909 plci->NL.ReqCh = 0;
10910 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10911 plci->adapter->request (&plci->NL);
10915 static void xconnect_write_coefs (PLCI *plci, word internal_command)
10918 dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10919 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10920 (char *)(FILE_), __LINE__, internal_command));
10922 plci->li_write_command = internal_command;
10923 plci->li_write_channel = 0;
10927 static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc)
10929 DIVA_CAPI_ADAPTER *a;
10930 word w, n, i, j, r, s, to_ch;
10933 struct xconnect_transfer_address_s *transfer_address;
10934 byte ch_map[MIXER_CHANNELS_BRI];
10936 dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10937 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10940 if ((plci->li_bchannel_id == 0)
10941 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10943 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10944 UnMapId (Id), (char *)(FILE_), __LINE__));
10947 i = a->li_base + (plci->li_bchannel_id - 1);
10948 j = plci->li_write_channel;
10949 p = plci->internal_req_buffer;
10952 if ((Rc != OK) && (Rc != OK_FC))
10954 dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10955 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
10959 if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10963 if (j < li_total_channels)
10965 if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10967 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10968 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10969 ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10970 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10972 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10973 while ((j < li_total_channels)
10975 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10976 || (!li_config_table[j].adapter->li_pri
10977 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10978 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10979 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10980 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10981 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10982 || ((li_config_table[j].adapter->li_base != a->li_base)
10984 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10985 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10986 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10987 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10990 if (j < li_total_channels)
10991 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10994 if (j < li_total_channels)
10996 plci->internal_command = plci->li_write_command;
10997 if (plci_nl_busy (plci))
10999 to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
11000 *(p++) = UDATA_REQUEST_XCONNECT_TO;
11003 if (li_config_table[j].adapter->li_base != a->li_base)
11006 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11007 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11008 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11009 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11014 if (r & xconnect_write_prog[n].mask)
11016 if (xconnect_write_prog[n].from_pc)
11017 transfer_address = &(li_config_table[j].send_pc);
11019 transfer_address = &(li_config_table[j].send_b);
11020 d = transfer_address->card_address.low;
11022 *(p++) = (byte)(d >> 8);
11023 *(p++) = (byte)(d >> 16);
11024 *(p++) = (byte)(d >> 24);
11025 d = transfer_address->card_address.high;
11027 *(p++) = (byte)(d >> 8);
11028 *(p++) = (byte)(d >> 16);
11029 *(p++) = (byte)(d >> 24);
11030 d = transfer_address->offset;
11032 *(p++) = (byte)(d >> 8);
11033 *(p++) = (byte)(d >> 16);
11034 *(p++) = (byte)(d >> 24);
11035 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11037 *(p++) = (byte)(w >> 8);
11038 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11039 (li_config_table[i].adapter->u_law ?
11040 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11041 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11044 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11047 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11048 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11049 if (n == ARRAY_SIZE(xconnect_write_prog))
11054 if (j < li_total_channels)
11055 r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11056 } while ((j < li_total_channels)
11058 || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11059 || (!li_config_table[j].adapter->li_pri
11060 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11061 || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11062 || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11063 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11064 || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11065 || ((li_config_table[j].adapter->li_base != a->li_base)
11067 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11068 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11069 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11070 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11072 } while ((j < li_total_channels)
11073 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11075 else if (j == li_total_channels)
11077 plci->internal_command = plci->li_write_command;
11078 if (plci_nl_busy (plci))
11082 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11084 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11085 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11086 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11087 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11089 *(p++) = (byte)(w >> 8);
11093 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11095 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11096 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11098 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11100 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11101 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11102 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11103 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11105 *(p++) = (byte)(w >> 8);
11106 for (j = 0; j < sizeof(ch_map); j += 2)
11108 if (plci->li_bchannel_id == 2)
11110 ch_map[j] = (byte)(j+1);
11111 ch_map[j+1] = (byte) j;
11115 ch_map[j] = (byte) j;
11116 ch_map[j+1] = (byte)(j+1);
11119 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11121 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11122 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11123 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11125 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11126 mixer_write_prog_bri[n].xconnect_override :
11127 ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11128 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11130 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11131 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11137 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11139 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11140 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11141 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11147 j = li_total_channels + 1;
11152 if (j <= li_total_channels)
11154 plci->internal_command = plci->li_write_command;
11155 if (plci_nl_busy (plci))
11157 if (j < a->li_base)
11161 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11163 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11164 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11165 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11166 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11168 *(p++) = (byte)(w >> 8);
11169 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11171 *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11172 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11174 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11175 if (w & mixer_write_prog_pri[n].mask)
11177 *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11178 li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11183 *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11184 for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11186 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11187 if (w & mixer_write_prog_pri[n].mask)
11189 *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11190 li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11199 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11201 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11202 && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11204 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11206 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11207 w |= MIXER_FEATURE_ENABLE_TX_DATA;
11208 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11209 w |= MIXER_FEATURE_ENABLE_RX_DATA;
11211 *(p++) = (byte)(w >> 8);
11212 for (j = 0; j < sizeof(ch_map); j += 2)
11214 if (plci->li_bchannel_id == 2)
11216 ch_map[j] = (byte)(j+1);
11217 ch_map[j+1] = (byte) j;
11221 ch_map[j] = (byte) j;
11222 ch_map[j+1] = (byte)(j+1);
11225 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11227 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11228 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11229 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11231 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11232 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11233 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11238 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11240 w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11241 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11242 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11248 j = li_total_channels + 1;
11251 plci->li_write_channel = j;
11252 if (p != plci->internal_req_buffer)
11254 plci->NData[0].P = plci->internal_req_buffer;
11255 plci->NData[0].PLength = p - plci->internal_req_buffer;
11256 plci->NL.X = plci->NData;
11257 plci->NL.ReqCh = 0;
11258 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11259 plci->adapter->request (&plci->NL);
11265 static void mixer_notify_update (PLCI *plci, byte others)
11267 DIVA_CAPI_ADAPTER *a;
11270 byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11272 dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11273 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11274 (char *)(FILE_), __LINE__, others));
11277 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11280 plci->li_notify_update = true;
11284 notify_plci = NULL;
11287 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11289 if (i < li_total_channels)
11290 notify_plci = li_config_table[i++].plci;
11294 if ((plci->li_bchannel_id != 0)
11295 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11297 notify_plci = plci;
11300 if ((notify_plci != NULL)
11301 && !notify_plci->li_notify_update
11302 && (notify_plci->appl != NULL)
11303 && (notify_plci->State)
11304 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11306 notify_plci->li_notify_update = true;
11307 ((CAPI_MSG *) msg)->header.length = 18;
11308 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11309 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11310 ((CAPI_MSG *) msg)->header.number = 0;
11311 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11312 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11313 ((CAPI_MSG *) msg)->header.ncci = 0;
11314 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11315 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11316 PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11317 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11318 w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11319 if (w != _QUEUE_FULL)
11323 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11324 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11325 (char *)(FILE_), __LINE__,
11326 (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11328 notify_plci->li_notify_update = false;
11331 } while (others && (notify_plci != NULL));
11333 plci->li_notify_update = false;
11338 static void mixer_clear_config (PLCI *plci)
11340 DIVA_CAPI_ADAPTER *a;
11343 dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11344 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11345 (char *)(FILE_), __LINE__));
11347 plci->li_notify_update = false;
11348 plci->li_plci_b_write_pos = 0;
11349 plci->li_plci_b_read_pos = 0;
11350 plci->li_plci_b_req_pos = 0;
11352 if ((plci->li_bchannel_id != 0)
11353 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11355 i = a->li_base + (plci->li_bchannel_id - 1);
11356 li_config_table[i].curchnl = 0;
11357 li_config_table[i].channel = 0;
11358 li_config_table[i].chflags = 0;
11359 for (j = 0; j < li_total_channels; j++)
11361 li_config_table[j].flag_table[i] = 0;
11362 li_config_table[i].flag_table[j] = 0;
11363 li_config_table[i].coef_table[j] = 0;
11364 li_config_table[j].coef_table[i] = 0;
11368 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11369 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11371 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11372 li_config_table[i].curchnl = 0;
11373 li_config_table[i].channel = 0;
11374 li_config_table[i].chflags = 0;
11375 for (j = 0; j < li_total_channels; j++)
11377 li_config_table[i].flag_table[j] = 0;
11378 li_config_table[j].flag_table[i] = 0;
11379 li_config_table[i].coef_table[j] = 0;
11380 li_config_table[j].coef_table[i] = 0;
11382 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11384 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11385 li_config_table[i].curchnl = 0;
11386 li_config_table[i].channel = 0;
11387 li_config_table[i].chflags = 0;
11388 for (j = 0; j < li_total_channels; j++)
11390 li_config_table[i].flag_table[j] = 0;
11391 li_config_table[j].flag_table[i] = 0;
11392 li_config_table[i].coef_table[j] = 0;
11393 li_config_table[j].coef_table[i] = 0;
11402 static void mixer_prepare_switch (dword Id, PLCI *plci)
11405 dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11406 UnMapId (Id), (char *)(FILE_), __LINE__));
11410 mixer_indication_coefs_set (Id, plci);
11411 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11415 static word mixer_save_config (dword Id, PLCI *plci, byte Rc)
11417 DIVA_CAPI_ADAPTER *a;
11420 dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11421 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11424 if ((plci->li_bchannel_id != 0)
11425 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11427 i = a->li_base + (plci->li_bchannel_id - 1);
11428 for (j = 0; j < li_total_channels; j++)
11430 li_config_table[i].coef_table[j] &= 0xf;
11431 li_config_table[j].coef_table[i] &= 0xf;
11434 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11440 static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
11442 DIVA_CAPI_ADAPTER *a;
11445 dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11446 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11450 if ((plci->B1_facilities & B1_FACILITY_MIXER)
11451 && (plci->li_bchannel_id != 0)
11452 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11454 switch (plci->adjust_b_state)
11456 case ADJUST_B_RESTORE_MIXER_1:
11457 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11459 plci->internal_command = plci->adjust_b_command;
11460 if (plci_nl_busy (plci))
11462 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11465 xconnect_query_addresses (plci);
11466 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11469 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11471 case ADJUST_B_RESTORE_MIXER_2:
11472 case ADJUST_B_RESTORE_MIXER_3:
11473 case ADJUST_B_RESTORE_MIXER_4:
11474 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11476 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11477 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
11478 Info = _WRONG_STATE;
11483 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11484 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11485 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11486 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11490 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11491 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11492 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11493 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11495 if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11497 plci->internal_command = plci->adjust_b_command;
11500 case ADJUST_B_RESTORE_MIXER_5:
11501 xconnect_write_coefs (plci, plci->adjust_b_command);
11502 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11504 case ADJUST_B_RESTORE_MIXER_6:
11505 if (!xconnect_write_coefs_process (Id, plci, Rc))
11507 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11508 UnMapId (Id), (char *)(FILE_), __LINE__));
11509 Info = _FACILITY_NOT_SUPPORTED;
11512 if (plci->internal_command)
11514 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11515 case ADJUST_B_RESTORE_MIXER_7:
11523 static void mixer_command (dword Id, PLCI *plci, byte Rc)
11525 DIVA_CAPI_ADAPTER *a;
11526 word i, internal_command, Info;
11528 dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11529 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11534 internal_command = plci->internal_command;
11535 plci->internal_command = 0;
11536 switch (plci->li_cmd)
11538 case LI_REQ_CONNECT:
11539 case LI_REQ_DISCONNECT:
11540 case LI_REQ_SILENT_UPDATE:
11541 switch (internal_command)
11544 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11546 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11547 B1_FACILITY_MIXER), MIXER_COMMAND_1);
11549 case MIXER_COMMAND_1:
11550 if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11552 if (adjust_b_process (Id, plci, Rc) != GOOD)
11554 dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11555 UnMapId (Id), (char *)(FILE_), __LINE__));
11556 Info = _FACILITY_NOT_SUPPORTED;
11559 if (plci->internal_command)
11562 plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11563 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11564 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11565 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11566 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11568 xconnect_write_coefs (plci, MIXER_COMMAND_2);
11574 mixer_indication_coefs_set (Id, plci);
11575 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11577 case MIXER_COMMAND_2:
11578 if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11579 || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11580 && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11581 ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11583 if (!xconnect_write_coefs_process (Id, plci, Rc))
11585 dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11586 UnMapId (Id), (char *)(FILE_), __LINE__));
11587 if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11591 plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11592 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11593 i = (plci->li_plci_b_write_pos == 0) ?
11594 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11595 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11596 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11598 Info = _FACILITY_NOT_SUPPORTED;
11601 if (plci->internal_command)
11604 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11606 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11607 ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11609 case MIXER_COMMAND_3:
11610 if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11612 if (adjust_b_process (Id, plci, Rc) != GOOD)
11614 dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11615 UnMapId (Id), (char *)(FILE_), __LINE__));
11616 Info = _FACILITY_NOT_SUPPORTED;
11619 if (plci->internal_command)
11626 if ((plci->li_bchannel_id == 0)
11627 || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11629 dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11630 UnMapId (Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11634 i = a->li_base + (plci->li_bchannel_id - 1);
11635 li_config_table[i].curchnl = plci->li_channel_bits;
11636 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11638 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11639 li_config_table[i].curchnl = plci->li_channel_bits;
11640 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11642 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11643 li_config_table[i].curchnl = plci->li_channel_bits;
11650 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11651 dword plci_b_id, byte connect, dword li_flags)
11653 word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11655 DIVA_CAPI_ADAPTER *a_b;
11657 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11658 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11659 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11660 if (!a->li_pri && (plci->tel == ADV_VOICE)
11661 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11663 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11664 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11665 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11672 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11673 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11674 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11676 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11677 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11678 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11687 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11688 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11689 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11690 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11692 li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11693 li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11694 li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11695 li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11696 if (ch_a_v == ch_b_v)
11698 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11699 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11703 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11705 for (i = 0; i < li_total_channels; i++)
11708 li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11711 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11713 for (i = 0; i < li_total_channels; i++)
11716 li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11719 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11721 for (i = 0; i < li_total_channels; i++)
11724 li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11727 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11729 for (i = 0; i < li_total_channels; i++)
11732 li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11736 if (li_flags & LI_FLAG_CONFERENCE_A_B)
11738 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11739 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11740 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11741 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11743 if (li_flags & LI_FLAG_CONFERENCE_B_A)
11745 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11746 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11747 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11748 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11750 if (li_flags & LI_FLAG_MONITOR_A)
11752 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11753 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11755 if (li_flags & LI_FLAG_MONITOR_B)
11757 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11758 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11760 if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11762 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11763 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11765 if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11767 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11768 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11770 if (li_flags & LI_FLAG_MIX_A)
11772 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11773 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11775 if (li_flags & LI_FLAG_MIX_B)
11777 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11778 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11780 if (ch_a_v != ch_a_s)
11782 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11783 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11785 if (ch_b_v != ch_b_s)
11787 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11788 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11793 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11794 dword plci_b_id, byte connect, dword li_flags)
11796 word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11798 DIVA_CAPI_ADAPTER *a_b;
11800 a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11801 plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11802 ch_a = a->li_base + (plci->li_bchannel_id - 1);
11803 if (!a->li_pri && (plci->tel == ADV_VOICE)
11804 && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11806 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11807 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11808 a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11815 ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11816 if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11817 && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11819 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11820 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11821 a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11830 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11831 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11832 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11833 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11834 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11835 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11837 li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11838 li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11839 li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11840 li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11841 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11842 li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11843 li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11844 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11845 if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11847 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11848 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11849 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11850 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11852 if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11854 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11859 if (li_flags & LI2_FLAG_MONITOR_B)
11861 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11862 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11864 if (li_flags & LI2_FLAG_MIX_B)
11866 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11867 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11869 if (li_flags & LI2_FLAG_MONITOR_X)
11870 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11871 if (li_flags & LI2_FLAG_MIX_X)
11872 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11873 if (li_flags & LI2_FLAG_LOOP_B)
11875 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11876 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11877 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11878 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11880 if (li_flags & LI2_FLAG_LOOP_PC)
11881 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11882 if (li_flags & LI2_FLAG_LOOP_X)
11883 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11884 if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11885 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11886 if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11887 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11888 if (ch_a_v != ch_a_s)
11890 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11891 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11893 if (ch_b_v != ch_b_s)
11895 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11896 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11901 static word li_check_main_plci (dword Id, PLCI *plci)
11905 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11906 UnMapId (Id), (char *)(FILE_), __LINE__));
11907 return (_WRONG_IDENTIFIER);
11910 || !plci->NL.Id || plci->nl_remove_id
11911 || (plci->li_bchannel_id == 0))
11913 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11914 UnMapId (Id), (char *)(FILE_), __LINE__));
11915 return (_WRONG_STATE);
11917 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11922 static PLCI *li_check_plci_b (dword Id, PLCI *plci,
11923 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11928 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11929 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11931 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11932 UnMapId (Id), (char *)(FILE_), __LINE__));
11933 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11937 if ((plci_b_id & 0x7f) != 0)
11939 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11940 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11944 || (((plci_b_id >> 8) & 0xff) == 0)
11945 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11947 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11948 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11949 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11952 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11954 || !plci_b->NL.Id || plci_b->nl_remove_id
11955 || (plci_b->li_bchannel_id == 0))
11957 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11958 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11959 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11962 li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11963 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11964 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11965 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11966 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11968 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11969 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
11970 PUT_WORD (p_result, _WRONG_IDENTIFIER);
11973 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11974 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11976 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11977 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11978 PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11985 static PLCI *li2_check_plci_b (dword Id, PLCI *plci,
11986 dword plci_b_id, word plci_b_write_pos, byte *p_result)
11991 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11992 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11994 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11995 UnMapId (Id), (char *)(FILE_), __LINE__));
11996 PUT_WORD (p_result, _WRONG_STATE);
12000 if ((plci_b_id & 0x7f) != 0)
12002 ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
12003 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
12007 || (((plci_b_id >> 8) & 0xff) == 0)
12008 || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
12010 dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
12011 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12012 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12015 plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12017 || !plci_b->NL.Id || plci_b->nl_remove_id
12018 || (plci_b->li_bchannel_id == 0)
12019 || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12021 dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12022 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12023 PUT_WORD (p_result, _WRONG_STATE);
12026 if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12027 ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12028 && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12029 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12031 dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12032 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id));
12033 PUT_WORD (p_result, _WRONG_IDENTIFIER);
12036 if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12037 (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12039 dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12040 UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12041 PUT_WORD (p_result, _WRONG_STATE);
12048 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12052 dword d, li_flags, plci_b_id;
12054 API_PARSE li_parms[3];
12055 API_PARSE li_req_parms[3];
12056 API_PARSE li_participant_struct[2];
12057 API_PARSE li_participant_parms[3];
12058 word participant_parms_pos;
12059 byte result_buffer[32];
12062 word plci_b_write_pos;
12064 dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12065 UnMapId (Id), (char *)(FILE_), __LINE__));
12068 result = result_buffer;
12069 result_buffer[0] = 0;
12070 if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12072 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12073 UnMapId (Id), (char *)(FILE_), __LINE__));
12074 Info = _FACILITY_NOT_SUPPORTED;
12076 else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12078 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12079 UnMapId (Id), (char *)(FILE_), __LINE__));
12080 Info = _WRONG_MESSAGE_FORMAT;
12084 result_buffer[0] = 3;
12085 PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12086 result_buffer[3] = 0;
12087 switch (GET_WORD (li_parms[0].info))
12089 case LI_GET_SUPPORTED_SERVICES:
12090 if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12092 result_buffer[0] = 17;
12093 result_buffer[3] = 14;
12094 PUT_WORD (&result_buffer[4], GOOD);
12096 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12097 d |= LI_CONFERENCING_SUPPORTED;
12098 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12099 d |= LI_MONITORING_SUPPORTED;
12100 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12101 d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12102 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12103 d |= LI_CROSS_CONTROLLER_SUPPORTED;
12104 PUT_DWORD (&result_buffer[6], d);
12105 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12108 for (i = 0; i < li_total_channels; i++)
12110 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12111 && (li_config_table[i].adapter->li_pri
12112 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12120 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12122 PUT_DWORD (&result_buffer[10], d / 2);
12123 PUT_DWORD (&result_buffer[14], d);
12127 result_buffer[0] = 25;
12128 result_buffer[3] = 22;
12129 PUT_WORD (&result_buffer[4], GOOD);
12130 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12131 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12132 d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12133 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12134 d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12135 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12136 d |= LI2_PC_LOOPING_SUPPORTED;
12137 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12138 d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12139 PUT_DWORD (&result_buffer[6], d);
12140 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12141 PUT_DWORD (&result_buffer[10], d / 2);
12142 PUT_DWORD (&result_buffer[14], d - 1);
12143 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12146 for (i = 0; i < li_total_channels; i++)
12148 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12149 && (li_config_table[i].adapter->li_pri
12150 || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12156 PUT_DWORD (&result_buffer[18], d / 2);
12157 PUT_DWORD (&result_buffer[22], d - 1);
12161 case LI_REQ_CONNECT:
12162 if (li_parms[1].length == 8)
12164 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12165 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12167 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12168 UnMapId (Id), (char *)(FILE_), __LINE__));
12169 Info = _WRONG_MESSAGE_FORMAT;
12172 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12173 li_flags = GET_DWORD (li_req_parms[1].info);
12174 Info = li_check_main_plci (Id, plci);
12175 result_buffer[0] = 9;
12176 result_buffer[3] = 6;
12177 PUT_DWORD (&result_buffer[4], plci_b_id);
12178 PUT_WORD (&result_buffer[8], GOOD);
12181 result = plci->saved_msg.info;
12182 for (i = 0; i <= result_buffer[0]; i++)
12183 result[i] = result_buffer[i];
12184 plci_b_write_pos = plci->li_plci_b_write_pos;
12185 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12186 if (plci_b == NULL)
12188 li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12189 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12190 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12191 plci->li_plci_b_write_pos = plci_b_write_pos;
12195 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12196 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12198 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12199 UnMapId (Id), (char *)(FILE_), __LINE__));
12200 Info = _WRONG_MESSAGE_FORMAT;
12203 li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12204 Info = li_check_main_plci (Id, plci);
12205 result_buffer[0] = 7;
12206 result_buffer[3] = 4;
12207 PUT_WORD (&result_buffer[4], Info);
12208 result_buffer[6] = 0;
12211 result = plci->saved_msg.info;
12212 for (i = 0; i <= result_buffer[0]; i++)
12213 result[i] = result_buffer[i];
12214 plci_b_write_pos = plci->li_plci_b_write_pos;
12215 participant_parms_pos = 0;
12217 li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12218 while (participant_parms_pos < li_req_parms[1].length)
12220 result[result_pos] = 6;
12222 PUT_DWORD (&result[result_pos - 6], 0);
12223 PUT_WORD (&result[result_pos - 2], GOOD);
12224 if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12225 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12227 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12228 UnMapId (Id), (char *)(FILE_), __LINE__));
12229 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12232 if (api_parse (&li_participant_struct[0].info[1],
12233 li_participant_struct[0].length, "dd", li_participant_parms))
12235 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12236 UnMapId (Id), (char *)(FILE_), __LINE__));
12237 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12240 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12241 li_flags = GET_DWORD (li_participant_parms[1].info);
12242 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12243 if (sizeof(result) - result_pos < 7)
12245 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12246 UnMapId (Id), (char *)(FILE_), __LINE__));
12247 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12250 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12251 if (plci_b != NULL)
12253 li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12254 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12255 ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12256 LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12257 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12259 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12260 (&li_req_parms[1].info[1]));
12262 result[0] = (byte)(result_pos - 1);
12263 result[3] = (byte)(result_pos - 4);
12264 result[6] = (byte)(result_pos - 7);
12265 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12266 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12267 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12269 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12270 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12273 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12274 plci->li_plci_b_write_pos = plci_b_write_pos;
12276 mixer_calculate_coefs (a);
12277 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12278 mixer_notify_update (plci, true);
12279 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12280 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12282 plci->li_cmd = GET_WORD (li_parms[0].info);
12283 start_internal_command (Id, plci, mixer_command);
12286 case LI_REQ_DISCONNECT:
12287 if (li_parms[1].length == 4)
12289 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12290 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12292 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12293 UnMapId (Id), (char *)(FILE_), __LINE__));
12294 Info = _WRONG_MESSAGE_FORMAT;
12297 plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12298 Info = li_check_main_plci (Id, plci);
12299 result_buffer[0] = 9;
12300 result_buffer[3] = 6;
12301 PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12302 PUT_WORD (&result_buffer[8], GOOD);
12305 result = plci->saved_msg.info;
12306 for (i = 0; i <= result_buffer[0]; i++)
12307 result[i] = result_buffer[i];
12308 plci_b_write_pos = plci->li_plci_b_write_pos;
12309 plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12310 if (plci_b == NULL)
12312 li_update_connect (Id, a, plci, plci_b_id, false, 0);
12313 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12314 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12315 plci->li_plci_b_write_pos = plci_b_write_pos;
12319 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12320 if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12322 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12323 UnMapId (Id), (char *)(FILE_), __LINE__));
12324 Info = _WRONG_MESSAGE_FORMAT;
12327 Info = li_check_main_plci (Id, plci);
12328 result_buffer[0] = 7;
12329 result_buffer[3] = 4;
12330 PUT_WORD (&result_buffer[4], Info);
12331 result_buffer[6] = 0;
12334 result = plci->saved_msg.info;
12335 for (i = 0; i <= result_buffer[0]; i++)
12336 result[i] = result_buffer[i];
12337 plci_b_write_pos = plci->li_plci_b_write_pos;
12338 participant_parms_pos = 0;
12340 while (participant_parms_pos < li_req_parms[0].length)
12342 result[result_pos] = 6;
12344 PUT_DWORD (&result[result_pos - 6], 0);
12345 PUT_WORD (&result[result_pos - 2], GOOD);
12346 if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12347 (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12349 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12350 UnMapId (Id), (char *)(FILE_), __LINE__));
12351 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12354 if (api_parse (&li_participant_struct[0].info[1],
12355 li_participant_struct[0].length, "d", li_participant_parms))
12357 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12358 UnMapId (Id), (char *)(FILE_), __LINE__));
12359 PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12362 plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12363 PUT_DWORD (&result[result_pos - 6], plci_b_id);
12364 if (sizeof(result) - result_pos < 7)
12366 dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12367 UnMapId (Id), (char *)(FILE_), __LINE__));
12368 PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12371 plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12372 if (plci_b != NULL)
12374 li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12375 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12376 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12378 participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12379 (&li_req_parms[0].info[1]));
12381 result[0] = (byte)(result_pos - 1);
12382 result[3] = (byte)(result_pos - 4);
12383 result[6] = (byte)(result_pos - 7);
12384 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12385 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12386 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12388 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12389 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12392 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12393 plci->li_plci_b_write_pos = plci_b_write_pos;
12395 mixer_calculate_coefs (a);
12396 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12397 mixer_notify_update (plci, true);
12398 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12399 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12401 plci->li_cmd = GET_WORD (li_parms[0].info);
12402 start_internal_command (Id, plci, mixer_command);
12405 case LI_REQ_SILENT_UPDATE:
12406 if (!plci || !plci->State
12407 || !plci->NL.Id || plci->nl_remove_id
12408 || (plci->li_bchannel_id == 0)
12409 || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12411 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12412 UnMapId (Id), (char *)(FILE_), __LINE__));
12415 plci_b_write_pos = plci->li_plci_b_write_pos;
12416 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12417 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12419 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12420 UnMapId (Id), (char *)(FILE_), __LINE__));
12423 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12424 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12425 || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12427 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12428 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12431 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12432 plci->li_plci_b_write_pos = plci_b_write_pos;
12433 plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12435 plci->li_cmd = GET_WORD (li_parms[0].info);
12436 start_internal_command (Id, plci, mixer_command);
12440 dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12441 UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12442 Info = _FACILITY_NOT_SUPPORTED;
12445 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12446 "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12451 static void mixer_indication_coefs_set (dword Id, PLCI *plci)
12454 DIVA_CAPI_ADAPTER *a;
12457 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12458 UnMapId (Id), (char *)(FILE_), __LINE__));
12461 if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12465 d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12466 if (!(d & LI_PLCI_B_SKIP_FLAG))
12468 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12470 if (d & LI_PLCI_B_DISC_FLAG)
12473 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12475 PUT_WORD (&result[4], _LI_USER_INITIATED);
12480 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12482 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12487 if (d & LI_PLCI_B_DISC_FLAG)
12490 PUT_WORD (&result[1], LI_IND_DISCONNECT);
12492 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12493 PUT_WORD (&result[8], _LI_USER_INITIATED);
12498 PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12500 PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12503 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12504 "ws", SELECTOR_LINE_INTERCONNECT, result);
12506 plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12507 0 : plci->li_plci_b_read_pos + 1;
12508 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12513 static void mixer_indication_xconnect_from (dword Id, PLCI *plci, byte *msg, word length)
12516 struct xconnect_transfer_address_s s, *p;
12517 DIVA_CAPI_ADAPTER *a;
12519 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12520 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12524 for (i = 1; i < length; i += 16)
12526 s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12527 s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12528 s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12529 ch = msg[i+12] | (msg[i+13] << 8);
12530 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12531 if (!a->li_pri && (plci->li_bchannel_id == 2))
12534 if (ch & XCONNECT_CHANNEL_PORT_PC)
12535 p = &(li_config_table[j].send_pc);
12537 p = &(li_config_table[j].send_b);
12538 p->card_address.low = s.card_address.low;
12539 p->card_address.high = s.card_address.high;
12540 p->offset = s.offset;
12541 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12543 if (plci->internal_command_queue[0]
12544 && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12545 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12546 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12548 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12549 if (!plci->internal_command)
12550 next_internal_command (Id, plci);
12552 mixer_notify_update (plci, true);
12556 static void mixer_indication_xconnect_to (dword Id, PLCI *plci, byte *msg, word length)
12559 dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12560 UnMapId (Id), (char *)(FILE_), __LINE__, (int) length));
12565 static byte mixer_notify_source_removed (PLCI *plci, dword plci_b_id)
12567 word plci_b_write_pos;
12569 plci_b_write_pos = plci->li_plci_b_write_pos;
12570 if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12571 LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12573 dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12574 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12575 (char *)(FILE_), __LINE__));
12578 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12579 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12580 plci->li_plci_b_write_pos = plci_b_write_pos;
12585 static void mixer_remove (PLCI *plci)
12587 DIVA_CAPI_ADAPTER *a;
12592 dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12593 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12594 (char *)(FILE_), __LINE__));
12597 plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12598 if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12600 if ((plci->li_bchannel_id != 0)
12601 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12603 i = a->li_base + (plci->li_bchannel_id - 1);
12604 if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12606 for (j = 0; j < li_total_channels; j++)
12608 if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12609 || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12611 notify_plci = li_config_table[j].plci;
12612 if ((notify_plci != NULL)
12613 && (notify_plci != plci)
12614 && (notify_plci->appl != NULL)
12615 && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12616 && (notify_plci->State)
12617 && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12619 mixer_notify_source_removed (notify_plci, plci_b_id);
12623 mixer_clear_config (plci);
12624 mixer_calculate_coefs (a);
12625 mixer_notify_update (plci, true);
12627 li_config_table[i].plci = NULL;
12628 plci->li_bchannel_id = 0;
12634 /*------------------------------------------------------------------*/
12635 /* Echo canceller facilities */
12636 /*------------------------------------------------------------------*/
12639 static void ec_write_parameters (PLCI *plci)
12642 byte parameter_buffer[6];
12644 dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12645 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12646 (char *)(FILE_), __LINE__));
12648 parameter_buffer[0] = 5;
12649 parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12650 PUT_WORD (¶meter_buffer[2], plci->ec_idi_options);
12651 plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12652 w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12653 PUT_WORD (¶meter_buffer[4], w);
12654 add_p (plci, FTY, parameter_buffer);
12655 sig_req (plci, TEL_CTRL, 0);
12660 static void ec_clear_config (PLCI *plci)
12663 dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12664 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12665 (char *)(FILE_), __LINE__));
12667 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12668 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12669 plci->ec_tail_length = 0;
12673 static void ec_prepare_switch (dword Id, PLCI *plci)
12676 dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12677 UnMapId (Id), (char *)(FILE_), __LINE__));
12682 static word ec_save_config (dword Id, PLCI *plci, byte Rc)
12685 dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12686 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12692 static word ec_restore_config (dword Id, PLCI *plci, byte Rc)
12696 dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12697 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12700 if (plci->B1_facilities & B1_FACILITY_EC)
12702 switch (plci->adjust_b_state)
12704 case ADJUST_B_RESTORE_EC_1:
12705 plci->internal_command = plci->adjust_b_command;
12708 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12711 ec_write_parameters (plci);
12712 plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12714 case ADJUST_B_RESTORE_EC_2:
12715 if ((Rc != OK) && (Rc != OK_FC))
12717 dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12718 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12719 Info = _WRONG_STATE;
12729 static void ec_command (dword Id, PLCI *plci, byte Rc)
12731 word internal_command, Info;
12734 dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12735 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12736 plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12739 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12742 PUT_WORD (&result[1], EC_SUCCESS);
12747 PUT_WORD (&result[1], plci->ec_cmd);
12749 PUT_WORD (&result[4], GOOD);
12751 internal_command = plci->internal_command;
12752 plci->internal_command = 0;
12753 switch (plci->ec_cmd)
12755 case EC_ENABLE_OPERATION:
12756 case EC_FREEZE_COEFFICIENTS:
12757 case EC_RESUME_COEFFICIENT_UPDATE:
12758 case EC_RESET_COEFFICIENTS:
12759 switch (internal_command)
12762 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12763 B1_FACILITY_EC), EC_COMMAND_1);
12765 if (adjust_b_process (Id, plci, Rc) != GOOD)
12767 dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12768 UnMapId (Id), (char *)(FILE_), __LINE__));
12769 Info = _FACILITY_NOT_SUPPORTED;
12772 if (plci->internal_command)
12777 plci->internal_command = EC_COMMAND_2;
12780 plci->internal_command = EC_COMMAND_3;
12781 ec_write_parameters (plci);
12784 if ((Rc != OK) && (Rc != OK_FC))
12786 dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12787 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12788 Info = _FACILITY_NOT_SUPPORTED;
12795 case EC_DISABLE_OPERATION:
12796 switch (internal_command)
12800 if (plci->B1_facilities & B1_FACILITY_EC)
12804 plci->internal_command = EC_COMMAND_1;
12807 plci->internal_command = EC_COMMAND_2;
12808 ec_write_parameters (plci);
12813 if ((Rc != OK) && (Rc != OK_FC))
12815 dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12816 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
12817 Info = _FACILITY_NOT_SUPPORTED;
12820 adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12821 ~B1_FACILITY_EC), EC_COMMAND_3);
12823 if (adjust_b_process (Id, plci, Rc) != GOOD)
12825 dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12826 UnMapId (Id), (char *)(FILE_), __LINE__));
12827 Info = _FACILITY_NOT_SUPPORTED;
12830 if (plci->internal_command)
12836 sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12837 "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12838 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12842 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg)
12846 API_PARSE ec_parms[3];
12849 dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12850 UnMapId (Id), (char *)(FILE_), __LINE__));
12854 if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12856 dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12857 UnMapId (Id), (char *)(FILE_), __LINE__));
12858 Info = _FACILITY_NOT_SUPPORTED;
12862 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12864 if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12866 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12867 UnMapId (Id), (char *)(FILE_), __LINE__));
12868 Info = _WRONG_MESSAGE_FORMAT;
12874 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12875 UnMapId (Id), (char *)(FILE_), __LINE__));
12876 Info = _WRONG_IDENTIFIER;
12878 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12880 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12881 UnMapId (Id), (char *)(FILE_), __LINE__));
12882 Info = _WRONG_STATE;
12887 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12888 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12890 PUT_WORD (&result[1], EC_SUCCESS);
12891 if (msg[1].length >= 4)
12893 opt = GET_WORD (&ec_parms[0].info[2]);
12894 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12895 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12896 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12897 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12898 if (opt & EC_DETECT_DISABLE_TONE)
12899 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12900 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12901 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12902 if (msg[1].length >= 6)
12904 plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12907 switch (plci->ec_cmd)
12909 case EC_ENABLE_OPERATION:
12910 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12911 start_internal_command (Id, plci, ec_command);
12914 case EC_DISABLE_OPERATION:
12915 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12916 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12917 LEC_RESET_COEFFICIENTS;
12918 start_internal_command (Id, plci, ec_command);
12921 case EC_FREEZE_COEFFICIENTS:
12922 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12923 start_internal_command (Id, plci, ec_command);
12926 case EC_RESUME_COEFFICIENT_UPDATE:
12927 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12928 start_internal_command (Id, plci, ec_command);
12931 case EC_RESET_COEFFICIENTS:
12932 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12933 start_internal_command (Id, plci, ec_command);
12937 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12938 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12939 PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12946 if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12948 dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12949 UnMapId (Id), (char *)(FILE_), __LINE__));
12950 Info = _WRONG_MESSAGE_FORMAT;
12954 if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12957 PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12959 PUT_WORD (&result[4], GOOD);
12960 PUT_WORD (&result[6], 0x0007);
12961 PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12962 PUT_WORD (&result[10], 0);
12964 else if (plci == NULL)
12966 dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12967 UnMapId (Id), (char *)(FILE_), __LINE__));
12968 Info = _WRONG_IDENTIFIER;
12970 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12972 dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12973 UnMapId (Id), (char *)(FILE_), __LINE__));
12974 Info = _WRONG_STATE;
12979 plci->ec_cmd = GET_WORD (ec_parms[0].info);
12980 plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12982 PUT_WORD (&result[1], plci->ec_cmd);
12984 PUT_WORD (&result[4], GOOD);
12985 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12986 LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12987 plci->ec_tail_length = 0;
12988 if (ec_parms[1].length >= 2)
12990 opt = GET_WORD (&ec_parms[1].info[1]);
12991 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12992 plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12993 if (opt & EC_DETECT_DISABLE_TONE)
12994 plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12995 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12996 plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12997 if (ec_parms[1].length >= 4)
12999 plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
13002 switch (plci->ec_cmd)
13004 case EC_ENABLE_OPERATION:
13005 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
13006 start_internal_command (Id, plci, ec_command);
13009 case EC_DISABLE_OPERATION:
13010 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
13011 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
13012 LEC_RESET_COEFFICIENTS;
13013 start_internal_command (Id, plci, ec_command);
13017 dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
13018 UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13019 PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13025 sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13026 "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13027 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13032 static void ec_indication (dword Id, PLCI *plci, byte *msg, word length)
13036 dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13037 UnMapId (Id), (char *)(FILE_), __LINE__));
13039 if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13041 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13044 PUT_WORD (&result[1], 0);
13047 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13048 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13050 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13051 PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13053 case LEC_DISABLE_RELEASED:
13054 PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13061 PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13063 PUT_WORD (&result[4], 0);
13066 case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13067 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13069 case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13070 PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13072 case LEC_DISABLE_RELEASED:
13073 PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13077 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13078 PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13084 /*------------------------------------------------------------------*/
13085 /* Advanced voice */
13086 /*------------------------------------------------------------------*/
13088 static void adv_voice_write_coefs (PLCI *plci, word write_command)
13090 DIVA_CAPI_ADAPTER *a;
13095 byte ch_map[MIXER_CHANNELS_BRI];
13097 byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13099 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13100 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13101 (char *)(FILE_), __LINE__, write_command));
13104 p = coef_buffer + 1;
13105 *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13107 while (i + sizeof(word) <= a->adv_voice_coef_length)
13109 PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13113 while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13115 PUT_WORD (p, 0x8000);
13120 if (!a->li_pri && (plci->li_bchannel_id == 0))
13122 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13124 plci->li_bchannel_id = 1;
13125 li_config_table[a->li_base].plci = plci;
13126 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13127 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13128 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13130 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13132 plci->li_bchannel_id = 2;
13133 li_config_table[a->li_base + 1].plci = plci;
13134 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13135 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13136 (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13139 if (!a->li_pri && (plci->li_bchannel_id != 0)
13140 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13142 i = a->li_base + (plci->li_bchannel_id - 1);
13143 switch (write_command)
13145 case ADV_VOICE_WRITE_ACTIVATION:
13146 j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13147 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13148 if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13150 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13151 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13153 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13155 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13156 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13157 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13158 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13160 mixer_calculate_coefs (a);
13161 li_config_table[i].curchnl = li_config_table[i].channel;
13162 li_config_table[j].curchnl = li_config_table[j].channel;
13163 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13164 li_config_table[k].curchnl = li_config_table[k].channel;
13167 case ADV_VOICE_WRITE_DEACTIVATION:
13168 for (j = 0; j < li_total_channels; j++)
13170 li_config_table[i].flag_table[j] = 0;
13171 li_config_table[j].flag_table[i] = 0;
13173 k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13174 for (j = 0; j < li_total_channels; j++)
13176 li_config_table[k].flag_table[j] = 0;
13177 li_config_table[j].flag_table[k] = 0;
13179 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13181 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13182 for (j = 0; j < li_total_channels; j++)
13184 li_config_table[k].flag_table[j] = 0;
13185 li_config_table[j].flag_table[k] = 0;
13188 mixer_calculate_coefs (a);
13191 if (plci->B1_facilities & B1_FACILITY_MIXER)
13194 if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13195 w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13196 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13197 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13198 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13199 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13201 *(p++) = (byte)(w >> 8);
13202 for (j = 0; j < sizeof(ch_map); j += 2)
13204 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13205 ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13207 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13209 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13210 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13211 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13213 *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13214 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13215 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13219 *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13220 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13226 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13227 *(p++) = a->adv_voice_coef_buffer[i];
13233 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13234 *(p++) = a->adv_voice_coef_buffer[i];
13236 coef_buffer[0] = (p - coef_buffer) - 1;
13237 add_p (plci, FTY, coef_buffer);
13238 sig_req (plci, TEL_CTRL, 0);
13243 static void adv_voice_clear_config (PLCI *plci)
13245 DIVA_CAPI_ADAPTER *a;
13250 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13251 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13252 (char *)(FILE_), __LINE__));
13255 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13257 a->adv_voice_coef_length = 0;
13259 if (!a->li_pri && (plci->li_bchannel_id != 0)
13260 && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13262 i = a->li_base + (plci->li_bchannel_id - 1);
13263 li_config_table[i].curchnl = 0;
13264 li_config_table[i].channel = 0;
13265 li_config_table[i].chflags = 0;
13266 for (j = 0; j < li_total_channels; j++)
13268 li_config_table[i].flag_table[j] = 0;
13269 li_config_table[j].flag_table[i] = 0;
13270 li_config_table[i].coef_table[j] = 0;
13271 li_config_table[j].coef_table[i] = 0;
13273 li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13274 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13275 li_config_table[i].curchnl = 0;
13276 li_config_table[i].channel = 0;
13277 li_config_table[i].chflags = 0;
13278 for (j = 0; j < li_total_channels; j++)
13280 li_config_table[i].flag_table[j] = 0;
13281 li_config_table[j].flag_table[i] = 0;
13282 li_config_table[i].coef_table[j] = 0;
13283 li_config_table[j].coef_table[i] = 0;
13285 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13287 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13288 li_config_table[i].curchnl = 0;
13289 li_config_table[i].channel = 0;
13290 li_config_table[i].chflags = 0;
13291 for (j = 0; j < li_total_channels; j++)
13293 li_config_table[i].flag_table[j] = 0;
13294 li_config_table[j].flag_table[i] = 0;
13295 li_config_table[i].coef_table[j] = 0;
13296 li_config_table[j].coef_table[i] = 0;
13305 static void adv_voice_prepare_switch (dword Id, PLCI *plci)
13308 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13309 UnMapId (Id), (char *)(FILE_), __LINE__));
13314 static word adv_voice_save_config (dword Id, PLCI *plci, byte Rc)
13317 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13318 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13324 static word adv_voice_restore_config (dword Id, PLCI *plci, byte Rc)
13326 DIVA_CAPI_ADAPTER *a;
13329 dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13330 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13334 if ((plci->B1_facilities & B1_FACILITY_VOICE)
13335 && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13337 switch (plci->adjust_b_state)
13339 case ADJUST_B_RESTORE_VOICE_1:
13340 plci->internal_command = plci->adjust_b_command;
13343 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13346 adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13347 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13349 case ADJUST_B_RESTORE_VOICE_2:
13350 if ((Rc != OK) && (Rc != OK_FC))
13352 dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13353 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13354 Info = _WRONG_STATE;
13366 /*------------------------------------------------------------------*/
13367 /* B1 resource switching */
13368 /*------------------------------------------------------------------*/
13370 static byte b1_facilities_table[] =
13372 0x00, /* 0 No bchannel resources */
13373 0x00, /* 1 Codec (automatic law) */
13374 0x00, /* 2 Codec (A-law) */
13375 0x00, /* 3 Codec (y-law) */
13376 0x00, /* 4 HDLC for X.21 */
13378 0x00, /* 6 External Device 0 */
13379 0x00, /* 7 External Device 1 */
13380 0x00, /* 8 HDLC 56k */
13381 0x00, /* 9 Transparent */
13382 0x00, /* 10 Loopback to network */
13383 0x00, /* 11 Test pattern to net */
13384 0x00, /* 12 Rate adaptation sync */
13385 0x00, /* 13 Rate adaptation async */
13386 0x00, /* 14 R-Interface */
13387 0x00, /* 15 HDLC 128k leased line */
13389 0x00, /* 17 Modem async */
13390 0x00, /* 18 Modem sync HDLC */
13391 0x00, /* 19 V.110 async HDLC */
13392 0x12, /* 20 Adv voice (Trans,mixer) */
13393 0x00, /* 21 Codec connected to IC */
13394 0x0c, /* 22 Trans,DTMF */
13395 0x1e, /* 23 Trans,DTMF+mixer */
13396 0x1f, /* 24 Trans,DTMF+mixer+local */
13397 0x13, /* 25 Trans,mixer+local */
13398 0x12, /* 26 HDLC,mixer */
13399 0x12, /* 27 HDLC 56k,mixer */
13400 0x2c, /* 28 Trans,LEC+DTMF */
13401 0x3e, /* 29 Trans,LEC+DTMF+mixer */
13402 0x3f, /* 30 Trans,LEC+DTMF+mixer+local */
13403 0x2c, /* 31 RTP,LEC+DTMF */
13404 0x3e, /* 32 RTP,LEC+DTMF+mixer */
13405 0x3f, /* 33 RTP,LEC+DTMF+mixer+local */
13406 0x00, /* 34 Signaling task */
13407 0x00, /* 35 PIAFS */
13408 0x0c, /* 36 Trans,DTMF+TONE */
13409 0x1e, /* 37 Trans,DTMF+TONE+mixer */
13410 0x1f /* 38 Trans,DTMF+TONE+mixer+local*/
13414 static word get_b1_facilities (PLCI * plci, byte b1_resource)
13416 word b1_facilities;
13418 b1_facilities = b1_facilities_table[b1_resource];
13419 if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13422 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13423 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13426 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13427 b1_facilities |= B1_FACILITY_DTMFX;
13428 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13429 b1_facilities |= B1_FACILITY_DTMFR;
13432 if ((b1_resource == 17) || (b1_resource == 18))
13434 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13435 b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13438 dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13439 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13440 (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13442 return (b1_facilities);
13446 static byte add_b1_facilities (PLCI * plci, byte b1_resource, word b1_facilities)
13450 switch (b1_resource)
13454 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13462 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13480 if (b1_facilities & B1_FACILITY_EC)
13482 if (b1_facilities & B1_FACILITY_LOCAL)
13484 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13490 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13491 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13492 || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13494 if (b1_facilities & B1_FACILITY_LOCAL)
13496 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13502 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13503 && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13504 || ((b1_facilities & B1_FACILITY_DTMFR)
13505 && ((b1_facilities & B1_FACILITY_MIXER)
13506 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13507 || ((b1_facilities & B1_FACILITY_DTMFX)
13508 && ((b1_facilities & B1_FACILITY_MIXER)
13509 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13511 if (b1_facilities & B1_FACILITY_LOCAL)
13513 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520 if (b1_facilities & B1_FACILITY_LOCAL)
13522 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13532 if (b1_facilities & B1_FACILITY_LOCAL)
13534 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13543 dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13544 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13545 (char *)(FILE_), __LINE__,
13546 b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13551 static void adjust_b1_facilities (PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13553 word removed_facilities;
13555 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13556 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13557 (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13558 new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13560 new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13561 removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13563 if (removed_facilities & B1_FACILITY_EC)
13564 ec_clear_config (plci);
13567 if (removed_facilities & B1_FACILITY_DTMFR)
13569 dtmf_rec_clear_config (plci);
13570 dtmf_parameter_clear_config (plci);
13572 if (removed_facilities & B1_FACILITY_DTMFX)
13573 dtmf_send_clear_config (plci);
13576 if (removed_facilities & B1_FACILITY_MIXER)
13577 mixer_clear_config (plci);
13579 if (removed_facilities & B1_FACILITY_VOICE)
13580 adv_voice_clear_config (plci);
13581 plci->B1_facilities = new_b1_facilities;
13585 static void adjust_b_clear (PLCI *plci)
13588 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13589 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13590 (char *)(FILE_), __LINE__));
13592 plci->adjust_b_restore = false;
13596 static word adjust_b_process (dword Id, PLCI *plci, byte Rc)
13603 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13604 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13607 switch (plci->adjust_b_state)
13609 case ADJUST_B_START:
13610 if ((plci->adjust_b_parms_msg == NULL)
13611 && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13612 && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13613 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13615 b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13616 0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13617 if (b1_resource == plci->B1_resource)
13619 adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13622 if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13624 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13625 UnMapId (Id), (char *)(FILE_), __LINE__,
13626 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13627 Info = _WRONG_STATE;
13631 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634 mixer_prepare_switch (Id, plci);
13637 dtmf_prepare_switch (Id, plci);
13638 dtmf_parameter_prepare_switch (Id, plci);
13641 ec_prepare_switch (Id, plci);
13643 adv_voice_prepare_switch (Id, plci);
13645 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13647 case ADJUST_B_SAVE_MIXER_1:
13648 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13651 Info = mixer_save_config (Id, plci, Rc);
13652 if ((Info != GOOD) || plci->internal_command)
13656 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13658 case ADJUST_B_SAVE_DTMF_1:
13659 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13662 Info = dtmf_save_config (Id, plci, Rc);
13663 if ((Info != GOOD) || plci->internal_command)
13667 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13668 case ADJUST_B_REMOVE_L23_1:
13669 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13670 && plci->NL.Id && !plci->nl_remove_id)
13672 plci->internal_command = plci->adjust_b_command;
13673 if (plci->adjust_b_ncci != 0)
13675 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13676 while (ncci_ptr->data_pending)
13678 plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13679 data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13681 while (ncci_ptr->data_ack_pending)
13682 data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13684 nl_req_ncci (plci, REMOVE,
13685 (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13687 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13690 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13692 case ADJUST_B_REMOVE_L23_2:
13693 if ((Rc != OK) && (Rc != OK_FC))
13695 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13696 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13697 Info = _WRONG_STATE;
13700 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13702 if (plci_nl_busy (plci))
13704 plci->internal_command = plci->adjust_b_command;
13708 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13710 case ADJUST_B_SAVE_EC_1:
13711 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13714 Info = ec_save_config (Id, plci, Rc);
13715 if ((Info != GOOD) || plci->internal_command)
13719 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13721 case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13722 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13725 Info = dtmf_parameter_save_config (Id, plci, Rc);
13726 if ((Info != GOOD) || plci->internal_command)
13730 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13732 case ADJUST_B_SAVE_VOICE_1:
13733 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13735 Info = adv_voice_save_config (Id, plci, Rc);
13736 if ((Info != GOOD) || plci->internal_command)
13739 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13740 case ADJUST_B_SWITCH_L1_1:
13741 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13745 plci->internal_command = plci->adjust_b_command;
13748 if (plci->adjust_b_parms_msg != NULL)
13749 api_load_msg (plci->adjust_b_parms_msg, bp);
13751 api_load_msg (&plci->B_protocol, bp);
13752 Info = add_b1 (plci, bp,
13753 (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13754 plci->adjust_b_facilities);
13757 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13758 UnMapId (Id), (char *)(FILE_), __LINE__,
13759 plci->B1_resource, plci->adjust_b_facilities));
13762 plci->internal_command = plci->adjust_b_command;
13763 sig_req (plci, RESOURCES, 0);
13765 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13768 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13770 case ADJUST_B_SWITCH_L1_2:
13771 if ((Rc != OK) && (Rc != OK_FC))
13773 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13774 UnMapId (Id), (char *)(FILE_), __LINE__,
13775 Rc, plci->B1_resource, plci->adjust_b_facilities));
13776 Info = _WRONG_STATE;
13779 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13781 case ADJUST_B_RESTORE_VOICE_1:
13782 case ADJUST_B_RESTORE_VOICE_2:
13783 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13785 Info = adv_voice_restore_config (Id, plci, Rc);
13786 if ((Info != GOOD) || plci->internal_command)
13789 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13791 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13792 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13793 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13796 Info = dtmf_parameter_restore_config (Id, plci, Rc);
13797 if ((Info != GOOD) || plci->internal_command)
13801 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13803 case ADJUST_B_RESTORE_EC_1:
13804 case ADJUST_B_RESTORE_EC_2:
13805 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13808 Info = ec_restore_config (Id, plci, Rc);
13809 if ((Info != GOOD) || plci->internal_command)
13813 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13814 case ADJUST_B_ASSIGN_L23_1:
13815 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13817 if (plci_nl_busy (plci))
13819 plci->internal_command = plci->adjust_b_command;
13822 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13823 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13824 if (plci->adjust_b_parms_msg != NULL)
13825 api_load_msg (plci->adjust_b_parms_msg, bp);
13827 api_load_msg (&plci->B_protocol, bp);
13828 Info = add_b23 (plci, bp);
13831 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13832 UnMapId (Id), (char *)(FILE_), __LINE__, Info));
13835 plci->internal_command = plci->adjust_b_command;
13836 nl_req_ncci (plci, ASSIGN, 0);
13838 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13841 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13843 case ADJUST_B_ASSIGN_L23_2:
13844 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13846 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13847 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13848 Info = _WRONG_STATE;
13851 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13853 if (Rc != ASSIGN_OK)
13855 plci->internal_command = plci->adjust_b_command;
13859 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13861 plci->adjust_b_restore = true;
13864 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13865 case ADJUST_B_CONNECT_1:
13866 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13868 plci->internal_command = plci->adjust_b_command;
13869 if (plci_nl_busy (plci))
13871 nl_req_ncci (plci, N_CONNECT, 0);
13873 plci->adjust_b_state = ADJUST_B_CONNECT_2;
13876 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13878 case ADJUST_B_CONNECT_2:
13879 case ADJUST_B_CONNECT_3:
13880 case ADJUST_B_CONNECT_4:
13881 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13883 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13884 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13885 Info = _WRONG_STATE;
13890 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13892 get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13893 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13895 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13896 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13897 else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13898 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13902 if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13903 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13904 else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13905 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13907 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13909 plci->internal_command = plci->adjust_b_command;
13913 case ADJUST_B_RESTORE_DTMF_1:
13914 case ADJUST_B_RESTORE_DTMF_2:
13915 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13918 Info = dtmf_restore_config (Id, plci, Rc);
13919 if ((Info != GOOD) || plci->internal_command)
13923 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13925 case ADJUST_B_RESTORE_MIXER_1:
13926 case ADJUST_B_RESTORE_MIXER_2:
13927 case ADJUST_B_RESTORE_MIXER_3:
13928 case ADJUST_B_RESTORE_MIXER_4:
13929 case ADJUST_B_RESTORE_MIXER_5:
13930 case ADJUST_B_RESTORE_MIXER_6:
13931 case ADJUST_B_RESTORE_MIXER_7:
13932 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13935 Info = mixer_restore_config (Id, plci, Rc);
13936 if ((Info != GOOD) || plci->internal_command)
13940 plci->adjust_b_state = ADJUST_B_END;
13948 static void adjust_b1_resource (dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command)
13951 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13952 UnMapId (Id), (char *)(FILE_), __LINE__,
13953 plci->B1_resource, b1_facilities));
13955 plci->adjust_b_parms_msg = bp_msg;
13956 plci->adjust_b_facilities = b1_facilities;
13957 plci->adjust_b_command = internal_command;
13958 plci->adjust_b_ncci = (word)(Id >> 16);
13959 if ((bp_msg == NULL) && (plci->B1_resource == 0))
13960 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13962 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13963 plci->adjust_b_state = ADJUST_B_START;
13964 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13965 UnMapId (Id), (char *)(FILE_), __LINE__,
13966 plci->B1_resource, b1_facilities));
13970 static void adjust_b_restore (dword Id, PLCI *plci, byte Rc)
13972 word internal_command;
13974 dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13975 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13977 internal_command = plci->internal_command;
13978 plci->internal_command = 0;
13979 switch (internal_command)
13983 if (plci->req_in != 0)
13985 plci->internal_command = ADJUST_B_RESTORE_1;
13989 case ADJUST_B_RESTORE_1:
13990 if ((Rc != OK) && (Rc != OK_FC))
13992 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13993 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
13995 plci->adjust_b_parms_msg = NULL;
13996 plci->adjust_b_facilities = plci->B1_facilities;
13997 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13998 plci->adjust_b_ncci = (word)(Id >> 16);
13999 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
14000 plci->adjust_b_state = ADJUST_B_START;
14001 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
14002 UnMapId (Id), (char *)(FILE_), __LINE__));
14003 case ADJUST_B_RESTORE_2:
14004 if (adjust_b_process (Id, plci, Rc) != GOOD)
14006 dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
14007 UnMapId (Id), (char *)(FILE_), __LINE__));
14009 if (plci->internal_command)
14016 static void reset_b3_command (dword Id, PLCI *plci, byte Rc)
14019 word internal_command;
14021 dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14022 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14025 internal_command = plci->internal_command;
14026 plci->internal_command = 0;
14027 switch (internal_command)
14031 plci->adjust_b_parms_msg = NULL;
14032 plci->adjust_b_facilities = plci->B1_facilities;
14033 plci->adjust_b_command = RESET_B3_COMMAND_1;
14034 plci->adjust_b_ncci = (word)(Id >> 16);
14035 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14036 plci->adjust_b_state = ADJUST_B_START;
14037 dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14038 UnMapId (Id), (char *)(FILE_), __LINE__));
14039 case RESET_B3_COMMAND_1:
14040 Info = adjust_b_process (Id, plci, Rc);
14043 dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14044 UnMapId (Id), (char *)(FILE_), __LINE__));
14047 if (plci->internal_command)
14051 /* sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14052 sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14056 static void select_b_command (dword Id, PLCI *plci, byte Rc)
14059 word internal_command;
14062 dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14063 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14066 internal_command = plci->internal_command;
14067 plci->internal_command = 0;
14068 switch (internal_command)
14072 plci->adjust_b_parms_msg = &plci->saved_msg;
14073 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14074 plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14076 plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14077 plci->adjust_b_command = SELECT_B_COMMAND_1;
14078 plci->adjust_b_ncci = (word)(Id >> 16);
14079 if (plci->saved_msg.parms[0].length == 0)
14081 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14082 ADJUST_B_MODE_NO_RESOURCE;
14086 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14087 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14089 plci->adjust_b_state = ADJUST_B_START;
14090 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14091 UnMapId (Id), (char *)(FILE_), __LINE__));
14092 case SELECT_B_COMMAND_1:
14093 Info = adjust_b_process (Id, plci, Rc);
14096 dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14097 UnMapId (Id), (char *)(FILE_), __LINE__));
14100 if (plci->internal_command)
14102 if (plci->tel == ADV_VOICE)
14106 esc_chi[2] = plci->b_channel;
14107 SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14111 sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14115 static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
14118 word internal_command;
14120 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14121 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14124 internal_command = plci->internal_command;
14125 plci->internal_command = 0;
14126 switch (internal_command)
14130 case FAX_CONNECT_ACK_COMMAND_1:
14131 if (plci_nl_busy (plci))
14133 plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14136 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14137 plci->NData[0].P = plci->fax_connect_info_buffer;
14138 plci->NData[0].PLength = plci->fax_connect_info_length;
14139 plci->NL.X = plci->NData;
14140 plci->NL.ReqCh = 0;
14141 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14142 plci->adapter->request (&plci->NL);
14144 case FAX_CONNECT_ACK_COMMAND_2:
14145 if ((Rc != OK) && (Rc != OK_FC))
14147 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14148 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14152 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14153 && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14155 if (plci->B3_prot == 4)
14156 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14158 sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14159 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14164 static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
14167 word internal_command;
14169 dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14170 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14173 internal_command = plci->internal_command;
14174 plci->internal_command = 0;
14175 switch (internal_command)
14179 case FAX_EDATA_ACK_COMMAND_1:
14180 if (plci_nl_busy (plci))
14182 plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14185 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14186 plci->NData[0].P = plci->fax_connect_info_buffer;
14187 plci->NData[0].PLength = plci->fax_edata_ack_length;
14188 plci->NL.X = plci->NData;
14189 plci->NL.ReqCh = 0;
14190 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14191 plci->adapter->request (&plci->NL);
14193 case FAX_EDATA_ACK_COMMAND_2:
14194 if ((Rc != OK) && (Rc != OK_FC))
14196 dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14197 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14204 static void fax_connect_info_command (dword Id, PLCI *plci, byte Rc)
14207 word internal_command;
14209 dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14210 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14213 internal_command = plci->internal_command;
14214 plci->internal_command = 0;
14215 switch (internal_command)
14219 case FAX_CONNECT_INFO_COMMAND_1:
14220 if (plci_nl_busy (plci))
14222 plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14225 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14226 plci->NData[0].P = plci->fax_connect_info_buffer;
14227 plci->NData[0].PLength = plci->fax_connect_info_length;
14228 plci->NL.X = plci->NData;
14229 plci->NL.ReqCh = 0;
14230 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14231 plci->adapter->request (&plci->NL);
14233 case FAX_CONNECT_INFO_COMMAND_2:
14234 if ((Rc != OK) && (Rc != OK_FC))
14236 dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14237 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14238 Info = _WRONG_STATE;
14241 if (plci_nl_busy (plci))
14243 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14246 plci->command = _CONNECT_B3_R;
14247 nl_req_ncci (plci, N_CONNECT, 0);
14251 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14255 static void fax_adjust_b23_command (dword Id, PLCI *plci, byte Rc)
14258 word internal_command;
14260 dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14261 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14264 internal_command = plci->internal_command;
14265 plci->internal_command = 0;
14266 switch (internal_command)
14270 plci->adjust_b_parms_msg = NULL;
14271 plci->adjust_b_facilities = plci->B1_facilities;
14272 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14273 plci->adjust_b_ncci = (word)(Id >> 16);
14274 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14275 plci->adjust_b_state = ADJUST_B_START;
14276 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14277 UnMapId (Id), (char *)(FILE_), __LINE__));
14278 case FAX_ADJUST_B23_COMMAND_1:
14279 Info = adjust_b_process (Id, plci, Rc);
14282 dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14283 UnMapId (Id), (char *)(FILE_), __LINE__));
14286 if (plci->internal_command)
14288 case FAX_ADJUST_B23_COMMAND_2:
14289 if (plci_nl_busy (plci))
14291 plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14294 plci->command = _CONNECT_B3_R;
14295 nl_req_ncci (plci, N_CONNECT, 0);
14299 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14303 static void fax_disconnect_command (dword Id, PLCI *plci, byte Rc)
14305 word internal_command;
14307 dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14308 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14310 internal_command = plci->internal_command;
14311 plci->internal_command = 0;
14312 switch (internal_command)
14316 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14318 case FAX_DISCONNECT_COMMAND_1:
14319 case FAX_DISCONNECT_COMMAND_2:
14320 case FAX_DISCONNECT_COMMAND_3:
14321 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14323 dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14324 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14329 if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14330 || (internal_command == FAX_DISCONNECT_COMMAND_2))
14332 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14337 if (internal_command == FAX_DISCONNECT_COMMAND_1)
14338 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14346 static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
14349 word internal_command;
14351 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14352 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14355 internal_command = plci->internal_command;
14356 plci->internal_command = 0;
14357 switch (internal_command)
14361 case RTP_CONNECT_B3_REQ_COMMAND_1:
14362 if (plci_nl_busy (plci))
14364 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14367 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14368 nl_req_ncci (plci, N_CONNECT, 0);
14371 case RTP_CONNECT_B3_REQ_COMMAND_2:
14372 if ((Rc != OK) && (Rc != OK_FC))
14374 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14375 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14376 Info = _WRONG_STATE;
14379 if (plci_nl_busy (plci))
14381 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14384 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14385 plci->NData[0].PLength = plci->internal_req_buffer[0];
14386 plci->NData[0].P = plci->internal_req_buffer + 1;
14387 plci->NL.X = plci->NData;
14388 plci->NL.ReqCh = 0;
14389 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14390 plci->adapter->request (&plci->NL);
14392 case RTP_CONNECT_B3_REQ_COMMAND_3:
14395 sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14399 static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
14402 word internal_command;
14404 dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14405 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14408 internal_command = plci->internal_command;
14409 plci->internal_command = 0;
14410 switch (internal_command)
14414 case RTP_CONNECT_B3_RES_COMMAND_1:
14415 if (plci_nl_busy (plci))
14417 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14420 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14421 nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14424 case RTP_CONNECT_B3_RES_COMMAND_2:
14425 if ((Rc != OK) && (Rc != OK_FC))
14427 dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14428 UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
14429 Info = _WRONG_STATE;
14432 if (plci_nl_busy (plci))
14434 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14437 sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14438 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14439 plci->NData[0].PLength = plci->internal_req_buffer[0];
14440 plci->NData[0].P = plci->internal_req_buffer + 1;
14441 plci->NL.X = plci->NData;
14442 plci->NL.ReqCh = 0;
14443 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14444 plci->adapter->request (&plci->NL);
14446 case RTP_CONNECT_B3_RES_COMMAND_3:
14453 static void hold_save_command (dword Id, PLCI *plci, byte Rc)
14455 byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14457 word internal_command;
14459 dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14460 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14463 internal_command = plci->internal_command;
14464 plci->internal_command = 0;
14465 switch (internal_command)
14471 plci->adjust_b_parms_msg = NULL;
14472 plci->adjust_b_facilities = plci->B1_facilities;
14473 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14474 plci->adjust_b_ncci = (word)(Id >> 16);
14475 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14476 plci->adjust_b_state = ADJUST_B_START;
14477 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14478 UnMapId (Id), (char *)(FILE_), __LINE__));
14479 case HOLD_SAVE_COMMAND_1:
14480 Info = adjust_b_process (Id, plci, Rc);
14483 dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14484 UnMapId (Id), (char *)(FILE_), __LINE__));
14487 if (plci->internal_command)
14490 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14494 static void retrieve_restore_command (dword Id, PLCI *plci, byte Rc)
14496 byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14498 word internal_command;
14500 dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14501 UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14504 internal_command = plci->internal_command;
14505 plci->internal_command = 0;
14506 switch (internal_command)
14510 plci->adjust_b_parms_msg = NULL;
14511 plci->adjust_b_facilities = plci->B1_facilities;
14512 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14513 plci->adjust_b_ncci = (word)(Id >> 16);
14514 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14515 plci->adjust_b_state = ADJUST_B_START;
14516 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14517 UnMapId (Id), (char *)(FILE_), __LINE__));
14518 case RETRIEVE_RESTORE_COMMAND_1:
14519 Info = adjust_b_process (Id, plci, Rc);
14522 dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14523 UnMapId (Id), (char *)(FILE_), __LINE__));
14526 if (plci->internal_command)
14529 sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14533 static void init_b1_config (PLCI *plci)
14536 dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14537 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14538 (char *)(FILE_), __LINE__));
14540 plci->B1_resource = 0;
14541 plci->B1_facilities = 0;
14543 plci->li_bchannel_id = 0;
14544 mixer_clear_config (plci);
14547 ec_clear_config (plci);
14550 dtmf_rec_clear_config (plci);
14551 dtmf_send_clear_config (plci);
14552 dtmf_parameter_clear_config (plci);
14554 adv_voice_clear_config (plci);
14555 adjust_b_clear (plci);
14559 static void clear_b1_config (PLCI *plci)
14562 dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14563 (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14564 (char *)(FILE_), __LINE__));
14566 adv_voice_clear_config (plci);
14567 adjust_b_clear (plci);
14569 ec_clear_config (plci);
14572 dtmf_rec_clear_config (plci);
14573 dtmf_send_clear_config (plci);
14574 dtmf_parameter_clear_config (plci);
14577 if ((plci->li_bchannel_id != 0)
14578 && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14580 mixer_clear_config (plci);
14581 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14582 plci->li_bchannel_id = 0;
14585 plci->B1_resource = 0;
14586 plci->B1_facilities = 0;
14590 /* -----------------------------------------------------------------
14591 XON protocol local helpers
14592 ----------------------------------------------------------------- */
14593 static void channel_flow_control_remove (PLCI * plci) {
14594 DIVA_CAPI_ADAPTER * a = plci->adapter;
14596 for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14597 if (a->ch_flow_plci[i] == plci->Id) {
14598 a->ch_flow_plci[i] = 0;
14599 a->ch_flow_control[i] = 0;
14604 static void channel_x_on (PLCI * plci, byte ch) {
14605 DIVA_CAPI_ADAPTER * a = plci->adapter;
14606 if (a->ch_flow_control[ch] & N_XON_SENT) {
14607 a->ch_flow_control[ch] &= ~N_XON_SENT;
14611 static void channel_x_off (PLCI * plci, byte ch, byte flag) {
14612 DIVA_CAPI_ADAPTER * a = plci->adapter;
14613 if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14614 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14615 a->ch_flow_plci[ch] = plci->Id;
14616 a->ch_flow_control_pending++;
14620 static void channel_request_xon (PLCI * plci, byte ch) {
14621 DIVA_CAPI_ADAPTER * a = plci->adapter;
14623 if (a->ch_flow_control[ch] & N_CH_XOFF) {
14624 a->ch_flow_control[ch] |= N_XON_REQ;
14625 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14626 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14630 static void channel_xmit_extended_xon (PLCI * plci) {
14631 DIVA_CAPI_ADAPTER * a;
14632 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14633 int i, one_requested = 0;
14635 if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14639 for (i = 0; i < max_ch; i++) {
14640 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14641 (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14642 (plci->Id == a->ch_flow_plci[i])) {
14643 channel_request_xon (plci, (byte)i);
14648 if (one_requested) {
14649 channel_xmit_xon (plci);
14654 Try to xmit next X_ON
14656 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER * a, PLCI * plci) {
14657 int max_ch = ARRAY_SIZE(a->ch_flow_control);
14660 if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14664 if (a->last_flow_control_ch >= max_ch) {
14665 a->last_flow_control_ch = 1;
14667 for (i=a->last_flow_control_ch; i < max_ch; i++) {
14668 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14669 (plci->Id == a->ch_flow_plci[i])) {
14670 a->last_flow_control_ch = i+1;
14675 for (i = 1; i < a->last_flow_control_ch; i++) {
14676 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14677 (plci->Id == a->ch_flow_plci[i])) {
14678 a->last_flow_control_ch = i+1;
14686 static void channel_xmit_xon (PLCI * plci) {
14687 DIVA_CAPI_ADAPTER * a = plci->adapter;
14690 if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14693 if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14696 a->ch_flow_control[ch] &= ~N_XON_REQ;
14697 a->ch_flow_control[ch] |= N_XON_SENT;
14699 plci->NL.Req = plci->nl_req = (byte)N_XON;
14700 plci->NL.ReqCh = ch;
14701 plci->NL.X = plci->NData;
14703 plci->NData[0].P = &plci->RBuffer[0];
14704 plci->NData[0].PLength = 0;
14706 plci->adapter->request(&plci->NL);
14709 static int channel_can_xon (PLCI * plci, byte ch) {
14711 DIVA_CAPI_ADAPTER * a;
14717 APPLptr = plci->appl;
14723 NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14725 /* count all buffers within the Application pool */
14726 /* belonging to the same NCCI. XON if a first is */
14730 for(i=0; i<APPLptr->MaxBuffer; i++) {
14731 if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14732 if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14734 if ((count > 2) || (Num == 0xffff)) {
14741 /*------------------------------------------------------------------*/
14743 static word CPN_filter_ok(byte *cpn,DIVA_CAPI_ADAPTER * a,word offset)
14750 /**********************************************************************************/
14751 /* function groups the listening applications according to the CIP mask and the */
14752 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14753 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14754 /* big problems on application level (one call, 30 Connect_Ind, ect). The */
14755 /* function must be enabled by setting "a->group_optimization_enabled" from the */
14756 /* OS specific part (per adapter). */
14757 /**********************************************************************************/
14758 static void group_optimization(DIVA_CAPI_ADAPTER * a, PLCI * plci)
14760 word i,j,k,busy,group_found;
14761 dword info_mask_group[MAX_CIP_TYPES];
14762 dword cip_mask_group[MAX_CIP_TYPES];
14763 word appl_number_group_type[MAX_APPL];
14766 set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14768 if(!a->group_optimization_enabled)
14770 dbug(1,dprintf("No group optimization"));
14774 dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14776 for(i=0;i<MAX_CIP_TYPES;i++)
14778 info_mask_group[i] = 0;
14779 cip_mask_group [i] = 0;
14781 for(i=0;i<MAX_APPL;i++)
14783 appl_number_group_type[i] = 0;
14785 for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14786 { /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14787 if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled ==1) )
14789 dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14790 return; /* allow good application unfiltered access */
14793 for(i=0; i<max_appl; i++) /* Build CIP Groups */
14795 if(application[i].Id && a->CIP_Mask[i] )
14797 for(k=0,busy=false; k<a->max_plci; k++)
14801 auxplci = &a->plci[k];
14802 if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14805 dbug(1,dprintf("Appl 0x%x is busy",i+1));
14807 else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14810 dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14815 for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++) /* build groups with free applications only */
14817 if(j==MAX_CIP_TYPES) /* all groups are in use but group still not found */
14818 { /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14819 appl_number_group_type[i] = MAX_CIP_TYPES;
14821 dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14823 else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )
14824 { /* is group already present ? */
14825 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14827 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]));
14829 else if(!info_mask_group[j])
14830 { /* establish a new group */
14831 appl_number_group_type[i] = j|0x80; /* store the group number for each application */
14832 info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group */
14833 cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group */
14835 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]));
14841 for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14843 if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14845 if(appl_number_group_type[i] == MAX_CIP_TYPES)
14847 dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14851 dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14852 for(j=i+1; j<max_appl; j++) /* search other group members and mark them as busy */
14854 if(appl_number_group_type[i] == appl_number_group_type[j])
14856 dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14857 clear_group_ind_mask_bit (plci, j); /* disable call on other group members */
14858 appl_number_group_type[j] = 0; /* remove disabled group member from group list */
14863 else /* application should not get a call */
14865 clear_group_ind_mask_bit (plci, i);
14873 /* OS notifies the driver about a application Capi_Register */
14874 word CapiRegister(word id)
14876 word i,j,appls_found;
14879 DIVA_CAPI_ADAPTER *a;
14881 for(i=0,appls_found=0; i<max_appl; i++)
14883 if( application[i].Id && (application[i].Id!=id) )
14885 appls_found++; /* an application has been found */
14889 if(appls_found) return true;
14890 for(i=0; i<max_adapter; i++) /* scan all adapters... */
14895 if(a->flag_dynamic_l1_down) /* remove adapter from L1 tristate (Huntgroup) */
14897 if(!appls_found) /* first application does a capi register */
14899 if((j=get_plci(a))) /* activate L1 of all adapters */
14901 plci = &a->plci[j-1];
14903 add_p(plci,OAD,"\x01\xfd");
14904 add_p(plci,CAI,"\x01\x80");
14905 add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14906 add_p(plci,SHIFT|6,NULL);
14907 add_p(plci,SIN,"\x02\x00\x00");
14908 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14909 sig_req(plci,ASSIGN,DSIG_ID);
14910 add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14911 sig_req(plci,SIG_CTRL,0);
14921 /*------------------------------------------------------------------*/
14923 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14925 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14928 /* Format of vswitch_t:
14931 2 byte VSWITCH_REQ/VSWITCH_IND
14933 4 word VSwitchcommand
14940 plci->Sig.Ind==NCR_FACILITY
14944 for(i=0;i<MAX_MULTI_IE;i++)
14946 if(!parms[i][0]) continue;
14949 parms[i][0]=0; /* kill it */
14952 dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14953 switch(parms[i][4])
14956 if(!plci->relatedPTYPLCI ||
14957 (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14961 /* remember all necessary informations */
14962 if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14966 if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14967 { /* first indication after ECT-Request on Consultation Call */
14968 plci->vswitchstate=parms[i][9];
14969 parms[i][9]=2; /* State */
14970 /* now ask first Call to join */
14972 else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14973 { /* Answer of VSWITCH_REQ from first Call */
14974 plci->vswitchstate=parms[i][9];
14975 /* tell consultation call to join
14976 and the protocol capabilities of the first call */
14982 plci->vsprot=parms[i][10]; /* protocol */
14983 plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14984 /* send join request to related PLCI */
14985 parms[i][1]=VSWITCHIE;
14986 parms[i][2]=VSWITCH_REQ;
14988 plci->relatedPTYPLCI->command = 0;
14989 plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14990 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14991 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14992 send_req(plci->relatedPTYPLCI);
14996 if(plci->relatedPTYPLCI &&
14997 plci->vswitchstate==3 &&
14998 plci->relatedPTYPLCI->vswitchstate==3)
15000 add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
15001 sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15002 send_req(plci->relatedPTYPLCI);
15006 parms[i][0]=0; /* kill it */
15011 /*------------------------------------------------------------------*/
15013 static int diva_get_dma_descriptor (PLCI *plci, dword *dma_magic) {
15015 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15017 if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15021 pReq->xdi_dma_descriptor_operation.Req = 0;
15022 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15024 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15025 pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
15026 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15027 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15029 e.user[0] = plci->adapter->Id - 1;
15030 plci->adapter->request((ENTITY*)pReq);
15032 if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15033 (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15034 pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15035 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15036 dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15038 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15040 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15042 dbug(1,dprintf("dma_alloc failed"));
15047 static void diva_free_dma_descriptor (PLCI *plci, int nr) {
15049 IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15055 pReq->xdi_dma_descriptor_operation.Req = 0;
15056 pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15058 pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15059 pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
15060 pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15061 pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
15063 e.user[0] = plci->adapter->Id - 1;
15064 plci->adapter->request((ENTITY*)pReq);
15066 if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15067 dbug(1,dprintf("dma_free(%d)", nr));
15069 dbug(1,dprintf("dma_free failed (%d)", nr));
15073 /*------------------------------------------------------------------*/